Bug 1786048 - Part 3: Merge nsIEmbeddingSiteWindow into nsIBaseWindow. r=emilio

Implementations of nsIEmbeddingSiteWindow and nsIBaseWindow largely
overlap, and where they don't, the nsIEmbeddingSiteWindow implementation
of the otherwise shared interface is primarily stubbed out with the
exception of Get/SetDimensions().

This patch moves a reimplementation of Get/SetDimensions() from
nsIEmbeddingSiteWindow to nsIBaseWindow. The other methods of
nsIEmbeddingSiteWindow remain covered by nsIBaseWindow.
Get/SetDimensions() can be implemented as part of nsIWebBrowserChrome
where nsIBaseWindow is not necessary. This removes the need for
nsIEmbeddingSiteWindow.

Blur() has also been moved to nsIWebBrowserChrome, as only
nsContentTreeOwner has an actual implementation which we in theory also
want to call from BrowserChild/Parent, but the spec suggests to
"selectively or uniformly ignore calls".

GetVisibility() had an implementation in BrowserChild that pretended to
always be visible. Instead of providing an interface for that,
nsDocShell now handles the not implemented case for tree owners.

nsIEmbeddingSiteWindow::GetSiteWindow() used to call through to
nsIBaseWindow::GetParentNativeWindow().

The Get/SetDimensions() implementation has been replaced with a strongly
typed setter, which is now also used directly from nsGlobalWindowOuter
to avoid problems that come with autodetecting unchanged dimensions,
when the current dimensions are outdated (e.g. immediately reverting a
change can be ignored).

Differential Revision: https://phabricator.services.mozilla.com/D160260
This commit is contained in:
Matthias Camenzind
2022-12-15 23:13:00 +00:00
parent 641877d61b
commit d634177ee2
39 changed files with 1170 additions and 681 deletions

View File

@@ -40,3 +40,19 @@ skip-if = debug # This test triggers Bug 1578794 due to opening many popups.
[browser_popup_new_window_size.js] [browser_popup_new_window_size.js]
support-files = support-files =
popup_size.html popup_size.html
[browser_popup_move.js]
skip-if = os == 'linux' && !headless # Wayland doesn't like moving windows, X11/XWayland unreliable current positions
[browser_popup_move_instant.js]
skip-if = os == 'linux' && !headless # Wayland doesn't like moving windows, X11/XWayland unreliable current positions
[browser_popup_resize.js]
skip-if = os == 'linux' && !headless # outdated current sizes
[browser_popup_resize_instant.js]
skip-if = os == 'linux' && !headless # outdated current sizes
[browser_popup_resize_repeat.js]
skip-if = os == 'linux' && !headless # outdated current sizes
[browser_popup_resize_repeat_instant.js]
skip-if = os == 'linux' && !headless # outdated current sizes
[browser_popup_resize_revert.js]
skip-if = os == 'linux' && !headless # outdated current sizes
[browser_popup_resize_revert_instant.js]
skip-if = os == 'linux' && !headless # outdated current sizes

View File

@@ -0,0 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericMoveTests(/* aInstant */ false, "Move");

View File

@@ -0,0 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericMoveTests(/* aInstant */ true, "Move");

View File

@@ -0,0 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(9, 10, /* aInstant */ false, "Resize");

View File

@@ -0,0 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(9, 10, /* aInstant */ true, "Resize");

View File

@@ -0,0 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(10, 10, /* aInstant */ false, "Resize repeat");

View File

@@ -0,0 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(10, 10, /* aInstant */ true, "Resize repeat");

View File

@@ -0,0 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(10, 0, /* aInstant */ false, "Resize revert");

View File

@@ -0,0 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
createGenericResizeTests(10, 0, /* aInstant */ true, "Resize revert");

View File

@@ -3,6 +3,10 @@
"use strict"; "use strict";
const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(
SpecialPowers.Ci.nsIGfxInfo
);
async function waitForBlockedPopups(numberOfPopups, { doc }) { async function waitForBlockedPopups(numberOfPopups, { doc }) {
let toolbarDoc = doc || document; let toolbarDoc = doc || document;
let menupopup = toolbarDoc.getElementById("blockedPopupOptions"); let menupopup = toolbarDoc.getElementById("blockedPopupOptions");
@@ -11,3 +15,476 @@ async function waitForBlockedPopups(numberOfPopups, { doc }) {
return popups.length == numberOfPopups; return popups.length == numberOfPopups;
}, `Waiting for ${numberOfPopups} popups`); }, `Waiting for ${numberOfPopups} popups`);
} }
/*
* Tests that a sequence of size changes ultimately results in the latest
* requested size. The test also fails when an unexpected window size is
* observed in a resize event.
*
* aPropertyDeltas List of objects where keys describe the name of a window
* property and the values the difference to its initial
* value.
*
* aInstant Issue changes without additional waiting in between.
*
* A brief example of the resutling code that is effectively run for the
* following list of deltas:
* [{outerWidth: 5, outerHeight: 10}, {outerWidth: 10}]
*
* let initialWidth = win.outerWidth;
* let initialHeight = win.outerHeight;
*
* if (aInstant) {
* win.outerWidth = initialWidth + 5;
* win.outerHeight = initialHeight + 10;
*
* win.outerWidth = initialWidth + 10;
* } else {
* win.requestAnimationFrame(() => {
* win.outerWidth = initialWidth + 5;
* win.outerHeight = initialHeight + 10;
*
* win.requestAnimationFrame(() => {
* win.outerWidth = initialWidth + 10;
* });
* });
* }
*/
async function testPropertyDeltas(aPropertyDeltas, aInstant, aPropInfo, aMsg) {
let msg = `[${aMsg}]`;
let win = this.content.popup || this.content.wrappedJSObject;
// Property names and mapping from ResizeMoveTest
let {
sizeProps,
positionProps /* can be empty/incomplete as workaround on Linux */,
readonlyProps,
crossBoundsMapping,
} = aPropInfo;
let stringifyState = state => {
let stateMsg = sizeProps
.concat(positionProps)
.filter(prop => state[prop] !== undefined)
.map(prop => `${prop}: ${state[prop]}`)
.join(", ");
return `{ ${stateMsg} }`;
};
let initialState = {};
let finalState = {};
info("Initializing all values to current state.");
for (let prop of sizeProps.concat(positionProps)) {
let value = win[prop];
initialState[prop] = value;
finalState[prop] = value;
}
// List of potential states during resize events. The current state is also
// considered valid, as the resize event might still be outstanding.
let validResizeStates = [initialState];
let updateFinalState = (aProp, aDelta) => {
if (
readonlyProps.includes(aProp) ||
!sizeProps.concat(positionProps).includes(aProp)
) {
throw new Error(`Unexpected property "${aProp}".`);
}
// Update both properties of the same axis.
let otherProp = crossBoundsMapping[aProp];
finalState[aProp] = initialState[aProp] + aDelta;
finalState[otherProp] = initialState[otherProp] + aDelta;
// Mark size as valid in resize event.
if (sizeProps.includes(aProp)) {
let state = {};
sizeProps.forEach(p => (state[p] = finalState[p]));
validResizeStates.push(state);
}
};
info("Adding resize event listener.");
let resizeCount = 0;
let resizeListener = evt => {
resizeCount++;
let currentSizeState = {};
sizeProps.forEach(p => (currentSizeState[p] = win[p]));
info(
`${msg} ${resizeCount}. resize event: ${stringifyState(currentSizeState)}`
);
let matchingIndex = validResizeStates.findIndex(state =>
sizeProps.every(p => state[p] == currentSizeState[p])
);
if (matchingIndex < 0) {
info(`${msg} Size state should have been one of:`);
for (let state of validResizeStates) {
info(stringifyState(state));
}
}
if (win.gBrowser && evt.target != win) {
// Without e10s we receive content resize events in chrome windows.
todo(false, `${msg} Resize event target is our window.`);
return;
}
ok(
matchingIndex >= 0,
`${msg} Valid intermediate state. Current: ` +
stringifyState(currentSizeState)
);
// No longer allow current and preceding states.
validResizeStates.splice(0, matchingIndex + 1);
};
win.addEventListener("resize", resizeListener);
info("Starting property changes.");
await new Promise(resolve => {
let index = 0;
let next = async () => {
let pre = `${msg} [${index + 1}/${aPropertyDeltas.length}]`;
let deltaObj = aPropertyDeltas[index];
for (let prop in deltaObj) {
updateFinalState(prop, deltaObj[prop]);
let targetValue = initialState[prop] + deltaObj[prop];
info(`${pre} Setting ${prop} to ${targetValue}.`);
win[prop] = targetValue;
}
index++;
if (index < aPropertyDeltas.length) {
scheduleNext();
} else {
resolve();
}
};
let scheduleNext = () => {
if (aInstant) {
next();
} else {
info(`${msg} Requesting animation frame.`);
win.requestAnimationFrame(next);
}
};
scheduleNext();
});
try {
info(`${msg} Waiting for window to match the final state.`);
await ContentTaskUtils.waitForCondition(
() => sizeProps.concat(positionProps).every(p => win[p] == finalState[p]),
"Waiting for final state."
);
} catch (e) {}
info(`${msg} Checking final state.`);
info(`${msg} Exepected: ${stringifyState(finalState)}`);
info(`${msg} Actual: ${stringifyState(win)}`);
for (let prop of sizeProps.concat(positionProps)) {
is(win[prop], finalState[prop], `${msg} Expected final value for ${prop}`);
}
win.removeEventListener("resize", resizeListener);
}
function roundedCenter(aDimension, aOrigin) {
let center = aOrigin + Math.floor(aDimension / 2);
return center - (center % 100);
}
class ResizeMoveTest {
static WindowWidth = 200;
static WindowHeight = 200;
static WindowLeft = roundedCenter(screen.availWidth - 200, screen.left);
static WindowTop = roundedCenter(screen.availHeight - 200, screen.top);
static PropInfo = {
sizeProps: ["outerWidth", "outerHeight", "innerWidth", "innerHeight"],
positionProps: [
"screenX",
"screenY",
/* readonly */ "mozInnerScreenX",
/* readonly */ "mozInnerScreenY",
],
readonlyProps: ["mozInnerScreenX", "mozInnerScreenY"],
crossAxisMapping: {
outerWidth: "outerHeight",
outerHeight: "outerWidth",
innerWidth: "innerHeight",
innerHeight: "innerWidth",
screenX: "screenY",
screenY: "screenX",
mozInnerScreenX: "mozInnerScreenY",
mozInnerScreenY: "mozInnerScreenX",
},
crossBoundsMapping: {
outerWidth: "innerWidth",
outerHeight: "innerHeight",
innerWidth: "outerWidth",
innerHeight: "outerHeight",
screenX: "mozInnerScreenX",
screenY: "mozInnerScreenY",
mozInnerScreenX: "screenX",
mozInnerScreenY: "screenY",
},
};
constructor(aPropertyDeltas, aInstant = false, aMsg = "ResizeMoveTest") {
this.propertyDeltas = aPropertyDeltas;
this.instant = aInstant;
this.msg = aMsg;
if (!ResizeMoveTest.hasCleanUpTask) {
ResizeMoveTest.hasCleanUpTask = true;
registerCleanupFunction(ResizeMoveTest.Cleanup);
}
add_task(async () => {
let tab = await ResizeMoveTest.GetOrCreateTab();
let browsingContext = await ResizeMoveTest.GetOrCreatePopupBrowsingContext();
if (!browsingContext) {
return;
}
info("=== Running in content. ===");
await this.run(browsingContext, `${this.msg} (content)`);
await this.restorePopupState(browsingContext);
info("=== Running in chrome. ===");
let popupChrome = browsingContext.topChromeWindow;
await this.run(popupChrome.browsingContext, `${this.msg} (chrome)`);
await this.restorePopupState(browsingContext);
info("=== Running in opener. ===");
await this.run(tab.linkedBrowser, `${this.msg} (opener)`);
await this.restorePopupState(browsingContext);
});
}
async run(aBrowsingContext, aMsg) {
let testType = this.instant ? "instant" : "fanned out";
let msg = `${aMsg} (${testType})`;
info(`${msg}: ` + JSON.stringify(this.propertyDeltas));
await SpecialPowers.spawn(
aBrowsingContext,
[this.propertyDeltas, this.instant, ResizeMoveTest.PropInfo, msg],
testPropertyDeltas
);
}
async restorePopupState(aBrowsingContext) {
info("Restore popup state.");
let { deltaWidth, deltaHeight } = await SpecialPowers.spawn(
aBrowsingContext,
[],
() => {
return {
deltaWidth: this.content.outerWidth - this.content.innerWidth,
deltaHeight: this.content.outerHeight - this.content.innerHeight,
};
}
);
let chromeWindow = aBrowsingContext.topChromeWindow;
let {
WindowLeft: left,
WindowTop: top,
WindowWidth: width,
WindowHeight: height,
} = ResizeMoveTest;
chromeWindow.resizeTo(width + deltaWidth, height + deltaHeight);
chromeWindow.moveTo(left, top);
await SpecialPowers.spawn(
aBrowsingContext,
[left, top, width, height],
async (aLeft, aTop, aWidth, aHeight) => {
let win = this.content.wrappedJSObject;
info("Waiting for restored size.");
await ContentTaskUtils.waitForCondition(
() => win.innerWidth == aWidth && win.innerHeight === aHeight,
"Waiting for restored size."
);
is(win.innerWidth, aWidth, "Restored width.");
is(win.innerHeight, aHeight, "Restored height.");
info("Waiting for restored position.");
await ContentTaskUtils.waitForCondition(
() => win.screenX == aLeft && win.screenY === aTop,
"Waiting for restored position."
);
is(win.screenX, aLeft, "Restored screenX.");
is(win.screenY, aTop, "Restored screenY.");
}
);
}
static async GetOrCreateTab() {
if (ResizeMoveTest.tab) {
return ResizeMoveTest.tab;
}
info("Opening tab.");
ResizeMoveTest.tab = await BrowserTestUtils.openNewForegroundTab(
window.gBrowser,
"https://example.net/browser/browser/base/content/test/popups/popup_blocker_a.html"
);
return ResizeMoveTest.tab;
}
static async GetOrCreatePopupBrowsingContext() {
if (ResizeMoveTest.popupBrowsingContext) {
if (!ResizeMoveTest.popupBrowsingContext.isActive) {
return undefined;
}
return ResizeMoveTest.popupBrowsingContext;
}
let tab = await ResizeMoveTest.GetOrCreateTab();
info("Opening popup.");
ResizeMoveTest.popupBrowsingContext = await SpecialPowers.spawn(
tab.linkedBrowser,
[
ResizeMoveTest.WindowWidth,
ResizeMoveTest.WindowHeight,
ResizeMoveTest.WindowLeft,
ResizeMoveTest.WindowTop,
],
async (aWidth, aHeight, aLeft, aTop) => {
let win = this.content.open(
this.content.document.location.href,
"_blank",
`left=${aLeft},top=${aTop},width=${aWidth},height=${aHeight}`
);
this.content.popup = win;
await new Promise(r => (win.onload = r));
return win.browsingContext;
}
);
return ResizeMoveTest.popupBrowsingContext;
}
static async Cleanup() {
let browsingContext = ResizeMoveTest.popupBrowsingContext;
if (browsingContext) {
await SpecialPowers.spawn(browsingContext, [], () => {
this.content.close();
});
delete ResizeMoveTest.popupBrowsingContext;
}
let tab = ResizeMoveTest.tab;
if (tab) {
await BrowserTestUtils.removeTab(tab);
delete ResizeMoveTest.tab;
}
ResizeMoveTest.hasCleanUpTask = false;
}
}
function chaosRequestLongerTimeout(aDoRequest) {
if (aDoRequest && parseInt(Services.env.get("MOZ_CHAOSMODE"), 16)) {
requestLongerTimeout(2);
}
}
function createGenericResizeTests(aFirstValue, aSecondValue, aInstant, aMsg) {
// Runtime almost doubles in chaos mode on Mac.
chaosRequestLongerTimeout(AppConstants.platform == "macosx");
let { crossBoundsMapping, crossAxisMapping } = ResizeMoveTest.PropInfo;
for (let prop of ["innerWidth", "outerHeight"]) {
// Mixing inner and outer property.
for (let secondProp of [prop, crossBoundsMapping[prop]]) {
let first = {};
first[prop] = aFirstValue;
let second = {};
second[secondProp] = aSecondValue;
new ResizeMoveTest(
[first, second],
aInstant,
`${aMsg} ${prop},${secondProp}`
);
}
}
for (let prop of ["innerHeight", "outerWidth"]) {
let first = {};
first[prop] = aFirstValue;
let second = {};
second[prop] = aSecondValue;
// Setting property of other axis before/between two changes.
let otherProps = [
crossAxisMapping[prop],
crossAxisMapping[crossBoundsMapping[prop]],
];
for (let interferenceProp of otherProps) {
let interference = {};
interference[interferenceProp] = 20;
new ResizeMoveTest(
[first, interference, second],
aInstant,
`${aMsg} ${prop},${interferenceProp},${prop}`
);
new ResizeMoveTest(
[interference, first, second],
aInstant,
`${aMsg} ${interferenceProp},${prop},${prop}`
);
}
}
}
function createGenericMoveTests(aInstant, aMsg) {
// Runtime almost doubles in chaos mode on Mac.
chaosRequestLongerTimeout(AppConstants.platform == "macosx");
let { crossAxisMapping } = ResizeMoveTest.PropInfo;
for (let prop of ["screenX", "screenY"]) {
for (let [v1, v2, msg] of [
[9, 10, `${aMsg}`],
[11, 11, `${aMsg} repeat`],
[12, 0, `${aMsg} revert`],
]) {
let first = {};
first[prop] = v1;
let second = {};
second[prop] = v2;
new ResizeMoveTest([first, second], aInstant, `${msg} ${prop},${prop}`);
let interferenceProp = crossAxisMapping[prop];
let interference = {};
interference[interferenceProp] = 20;
new ResizeMoveTest(
[first, interference, second],
aInstant,
`${aMsg} ${prop},${interferenceProp},${prop}`
);
new ResizeMoveTest(
[interference, first, second],
aInstant,
`${msg} ${interferenceProp},${prop},${prop}`
);
}
}
}

View File

@@ -4783,6 +4783,17 @@ void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
} }
} }
NS_IMETHODIMP
nsDocShell::SetDimensions(DimensionRequest&& aRequest) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::Repaint(bool aForce) { nsDocShell::Repaint(bool aForce) {
PresShell* presShell = GetPresShell(); PresShell* presShell = GetPresShell();
@@ -4908,7 +4919,13 @@ nsDocShell::GetVisibility(bool* aVisibility) {
// Check with the tree owner as well to give embedders a chance to // Check with the tree owner as well to give embedders a chance to
// expose visibility as well. // expose visibility as well.
return treeOwnerAsWin->GetVisibility(aVisibility); nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility);
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
// The tree owner had no opinion on our visibility.
*aVisibility = true;
return NS_OK;
}
return rv;
} }
void nsDocShell::ActivenessMaybeChanged() { void nsDocShell::ActivenessMaybeChanged() {

View File

@@ -554,68 +554,62 @@ nsDocShellTreeOwner::SetPositionDesktopPix(int32_t aX, int32_t aY) {
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::SetPosition(int32_t aX, int32_t aY) { nsDocShellTreeOwner::SetPosition(int32_t aX, int32_t aY) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); return SetDimensions(
if (ownerWin) { {DimensionKind::Outer, Some(aX), Some(aY), Nothing(), Nothing()});
return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
aX, aY, 0, 0);
}
return NS_ERROR_NULL_POINTER;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::GetPosition(int32_t* aX, int32_t* aY) { nsDocShellTreeOwner::GetPosition(int32_t* aX, int32_t* aY) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); return GetDimensions(DimensionKind::Outer, aX, aY, nullptr, nullptr);
if (ownerWin) {
return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
aX, aY, nullptr, nullptr);
}
return NS_ERROR_NULL_POINTER;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) { nsDocShellTreeOwner::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); return SetDimensions(
if (ownerWin) { {DimensionKind::Outer, Nothing(), Nothing(), Some(aCX), Some(aCY)});
return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER,
0, 0, aCX, aCY);
}
return NS_ERROR_NULL_POINTER;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::GetSize(int32_t* aCX, int32_t* aCY) { nsDocShellTreeOwner::GetSize(int32_t* aCX, int32_t* aCY) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); return GetDimensions(DimensionKind::Outer, nullptr, nullptr, aCX, aCY);
if (ownerWin) {
return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER,
nullptr, nullptr, aCX, aCY);
}
return NS_ERROR_NULL_POINTER;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aCX, nsDocShellTreeOwner::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aCX,
int32_t aCY, uint32_t aFlags) { int32_t aCY, uint32_t aFlags) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); return SetDimensions(
if (ownerWin) { {DimensionKind::Outer, Some(aX), Some(aY), Some(aCX), Some(aCY)});
return ownerWin->SetDimensions(
nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER |
nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
aX, aY, aCX, aCY);
}
return NS_ERROR_NULL_POINTER;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aCX, nsDocShellTreeOwner::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aCX,
int32_t* aCY) { int32_t* aCY) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); return GetDimensions(DimensionKind::Outer, aX, aY, aCX, aCY);
}
NS_IMETHODIMP
nsDocShellTreeOwner::SetDimensions(DimensionRequest&& aRequest) {
nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
if (ownerWin) { if (ownerWin) {
return ownerWin->GetDimensions( return ownerWin->SetDimensions(std::move(aRequest));
nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER |
nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
aX, aY, aCX, aCY);
} }
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
NS_ENSURE_STATE(webBrowserChrome);
return webBrowserChrome->SetDimensions(std::move(aRequest));
}
NS_IMETHODIMP
nsDocShellTreeOwner::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
if (ownerWin) {
return ownerWin->GetDimensions(aDimensionKind, aX, aY, aCX, aCY);
}
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
NS_ENSURE_STATE(webBrowserChrome);
return webBrowserChrome->GetDimensions(aDimensionKind, aX, aY, aCX, aCY);
} }
NS_IMETHODIMP NS_IMETHODIMP
@@ -633,9 +627,9 @@ nsDocShellTreeOwner::SetParentWidget(nsIWidget* aParentWidget) {
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::GetParentNativeWindow(nativeWindow* aParentNativeWindow) { nsDocShellTreeOwner::GetParentNativeWindow(nativeWindow* aParentNativeWindow) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
if (ownerWin) { if (ownerWin) {
return ownerWin->GetSiteWindow(aParentNativeWindow); return ownerWin->GetParentNativeWindow(aParentNativeWindow);
} }
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
} }
@@ -653,16 +647,17 @@ nsDocShellTreeOwner::GetNativeHandle(nsAString& aNativeHandle) {
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::GetVisibility(bool* aVisibility) { nsDocShellTreeOwner::GetVisibility(bool* aVisibility) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
if (ownerWin) { if (ownerWin) {
return ownerWin->GetVisibility(aVisibility); return ownerWin->GetVisibility(aVisibility);
} }
return NS_ERROR_NULL_POINTER;
return NS_ERROR_NOT_IMPLEMENTED;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::SetVisibility(bool aVisibility) { nsDocShellTreeOwner::SetVisibility(bool aVisibility) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
if (ownerWin) { if (ownerWin) {
return ownerWin->SetVisibility(aVisibility); return ownerWin->SetVisibility(aVisibility);
} }
@@ -688,7 +683,7 @@ nsDocShellTreeOwner::GetMainWidget(nsIWidget** aMainWidget) {
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::GetTitle(nsAString& aTitle) { nsDocShellTreeOwner::GetTitle(nsAString& aTitle) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
if (ownerWin) { if (ownerWin) {
return ownerWin->GetTitle(aTitle); return ownerWin->GetTitle(aTitle);
} }
@@ -697,7 +692,7 @@ nsDocShellTreeOwner::GetTitle(nsAString& aTitle) {
NS_IMETHODIMP NS_IMETHODIMP
nsDocShellTreeOwner::SetTitle(const nsAString& aTitle) { nsDocShellTreeOwner::SetTitle(const nsAString& aTitle) {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); nsCOMPtr<nsIBaseWindow> ownerWin = GetOwnerWin();
if (ownerWin) { if (ownerWin) {
return ownerWin->SetTitle(aTitle); return ownerWin->SetTitle(aTitle);
} }
@@ -819,8 +814,7 @@ nsDocShellTreeOwner::SetWebBrowserChrome(
if (supportsweak) { if (supportsweak) {
supportsweak->GetWeakReference(getter_AddRefs(mWebBrowserChromeWeak)); supportsweak->GetWeakReference(getter_AddRefs(mWebBrowserChromeWeak));
} else { } else {
nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin( nsCOMPtr<nsIBaseWindow> ownerWin(do_QueryInterface(aWebBrowserChrome));
do_QueryInterface(aWebBrowserChrome));
nsCOMPtr<nsIInterfaceRequestor> requestor( nsCOMPtr<nsIInterfaceRequestor> requestor(
do_QueryInterface(aWebBrowserChrome)); do_QueryInterface(aWebBrowserChrome));
@@ -992,8 +986,8 @@ nsDocShellTreeOwner::GetWebBrowserChrome() {
return chrome.forget(); return chrome.forget();
} }
already_AddRefed<nsIEmbeddingSiteWindow> nsDocShellTreeOwner::GetOwnerWin() { already_AddRefed<nsIBaseWindow> nsDocShellTreeOwner::GetOwnerWin() {
nsCOMPtr<nsIEmbeddingSiteWindow> win; nsCOMPtr<nsIBaseWindow> win;
if (mWebBrowserChromeWeak) { if (mWebBrowserChromeWeak) {
win = do_QueryReferent(mWebBrowserChromeWeak); win = do_QueryReferent(mWebBrowserChromeWeak);
} else if (mOwnerWin) { } else if (mOwnerWin) {

View File

@@ -18,7 +18,6 @@
#include "nsIInterfaceRequestorUtils.h" #include "nsIInterfaceRequestorUtils.h"
#include "nsIWebBrowserChrome.h" #include "nsIWebBrowserChrome.h"
#include "nsIDOMEventListener.h" #include "nsIDOMEventListener.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIWebProgressListener.h" #include "nsIWebProgressListener.h"
#include "nsWeakReference.h" #include "nsWeakReference.h"
#include "nsITimer.h" #include "nsITimer.h"
@@ -82,7 +81,7 @@ class nsDocShellTreeOwner final : public nsIDocShellTreeOwner,
// that object. Otherwise, they return an addrefed pointer. If the // that object. Otherwise, they return an addrefed pointer. If the
// WebBrowserChrome object doesn't exist, they return nullptr. // WebBrowserChrome object doesn't exist, they return nullptr.
already_AddRefed<nsIWebBrowserChrome> GetWebBrowserChrome(); already_AddRefed<nsIWebBrowserChrome> GetWebBrowserChrome();
already_AddRefed<nsIEmbeddingSiteWindow> GetOwnerWin(); already_AddRefed<nsIBaseWindow> GetOwnerWin();
already_AddRefed<nsIInterfaceRequestor> GetOwnerRequestor(); already_AddRefed<nsIInterfaceRequestor> GetOwnerRequestor();
protected: protected:
@@ -92,7 +91,7 @@ class nsDocShellTreeOwner final : public nsIDocShellTreeOwner,
nsIDocShellTreeItem* mPrimaryContentShell; nsIDocShellTreeItem* mPrimaryContentShell;
nsIWebBrowserChrome* mWebBrowserChrome; nsIWebBrowserChrome* mWebBrowserChrome;
nsIEmbeddingSiteWindow* mOwnerWin; nsIBaseWindow* mOwnerWin;
nsIInterfaceRequestor* mOwnerRequestor; nsIInterfaceRequestor* mOwnerRequestor;
nsWeakPtr mWebBrowserChromeWeak; // nsIWebBrowserChrome nsWeakPtr mWebBrowserChromeWeak; // nsIWebBrowserChrome

View File

@@ -133,7 +133,6 @@
#include "mozilla/dom/Document.h" #include "mozilla/dom/Document.h"
#include "Crypto.h" #include "Crypto.h"
#include "nsDOMString.h" #include "nsDOMString.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsILoadContext.h" #include "nsILoadContext.h"
#include "nsIScrollableFrame.h" #include "nsIScrollableFrame.h"
@@ -3527,40 +3526,66 @@ nsresult nsGlobalWindowOuter::GetInnerWidth(double* aInnerWidth) {
FORWARD_TO_INNER(GetInnerWidth, (aInnerWidth), NS_ERROR_UNEXPECTED); FORWARD_TO_INNER(GetInnerWidth, (aInnerWidth), NS_ERROR_UNEXPECTED);
} }
void nsGlobalWindowOuter::SetInnerWidthOuter(double aInnerWidth, void nsGlobalWindowOuter::SetInnerSize(int32_t aLengthCSSPixels, bool aIsWidth,
CallerType aCallerType, mozilla::dom::CallerType aCallerType,
ErrorResult& aError) { mozilla::ErrorResult& aError) {
if (!mDocShell) { if (!mDocShell) {
aError.Throw(NS_ERROR_UNEXPECTED); aError.Throw(NS_ERROR_UNEXPECTED);
return; return;
} }
// We only allow setting integers, for now. CSSIntCoord length(aLengthCSSPixels);
int32_t value = std::round(ToZeroIfNonfinite(aInnerWidth));
CheckSecurityWidthAndHeight((aIsWidth ? &length.value : nullptr),
(aIsWidth ? nullptr : &length.value),
aCallerType);
CheckSecurityWidthAndHeight(&value, nullptr, aCallerType);
RefPtr<PresShell> presShell = mDocShell->GetPresShell(); RefPtr<PresShell> presShell = mDocShell->GetPresShell();
// Setting inner width should set the CSS viewport. If the CSS viewport // Setting inner size should set the CSS viewport. If the CSS viewport
// has been overridden, change the override. // has been overridden, change the override.
if (presShell && presShell->UsesMobileViewportSizing()) { if (presShell && presShell->UsesMobileViewportSizing()) {
nscoord height = 0;
RefPtr<nsPresContext> presContext; RefPtr<nsPresContext> presContext;
presContext = presShell->GetPresContext(); presContext = presShell->GetPresContext();
nsRect shellArea = presContext->GetVisibleArea(); nsRect shellArea = presContext->GetVisibleArea();
height = shellArea.Height(); if (aIsWidth) {
SetCSSViewportWidthAndHeight(CSSPixel::ToAppUnits(value), height); shellArea.width = CSSPixel::ToAppUnits(CSSCoord(length));
} else {
shellArea.height = CSSPixel::ToAppUnits(CSSCoord(length));
}
SetCSSViewportWidthAndHeight(shellArea.Width(), shellArea.Height());
return; return;
} }
// Nothing has been overridden, so change the docshell itself. nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell)); if (!treeOwnerAsWin) {
LayoutDeviceIntSize size = docShellAsWin->GetSize(); aError.Throw(NS_ERROR_FAILURE);
size.width = return;
(CSSCoord(value) * CSSToDevScaleForBaseWindow(docShellAsWin)).Rounded(); }
aError = SetDocShellSize(size);
auto scale = CSSToDevScaleForBaseWindow(treeOwnerAsWin);
LayoutDeviceIntCoord valueDev = (CSSCoord(length) * scale).Rounded();
Maybe<LayoutDeviceIntCoord> width, height;
if (aIsWidth) {
width.emplace(valueDev);
} else {
height.emplace(valueDev);
}
aError = treeOwnerAsWin->SetDimensions(
{DimensionKind::Inner, Nothing(), Nothing(), width, height});
CheckForDPIChange();
}
void nsGlobalWindowOuter::SetInnerWidthOuter(double aInnerWidth,
CallerType aCallerType,
ErrorResult& aError) {
SetInnerSize(NSToIntRound(ToZeroIfNonfinite(aInnerWidth)),
/* aIsWidth */ true, aCallerType, aError);
} }
double nsGlobalWindowOuter::GetInnerHeightOuter(ErrorResult& aError) { double nsGlobalWindowOuter::GetInnerHeightOuter(ErrorResult& aError) {
@@ -3576,35 +3601,8 @@ nsresult nsGlobalWindowOuter::GetInnerHeight(double* aInnerHeight) {
void nsGlobalWindowOuter::SetInnerHeightOuter(double aInnerHeight, void nsGlobalWindowOuter::SetInnerHeightOuter(double aInnerHeight,
CallerType aCallerType, CallerType aCallerType,
ErrorResult& aError) { ErrorResult& aError) {
if (!mDocShell) { SetInnerSize(NSToIntRound(ToZeroIfNonfinite(aInnerHeight)),
aError.Throw(NS_ERROR_UNEXPECTED); /* aIsWidth */ false, aCallerType, aError);
return;
}
int32_t value = std::round(ToZeroIfNonfinite(aInnerHeight));
CheckSecurityWidthAndHeight(nullptr, &value, aCallerType);
RefPtr<PresShell> presShell = mDocShell->GetPresShell();
// Setting inner height should set the CSS viewport. If the CSS viewport
// has been overridden, change the override.
if (presShell && presShell->UsesMobileViewportSizing()) {
nscoord width = 0;
RefPtr<nsPresContext> presContext;
presContext = presShell->GetPresContext();
nsRect shellArea = presContext->GetVisibleArea();
width = shellArea.Width();
SetCSSViewportWidthAndHeight(width, CSSPixel::ToAppUnits(value));
return;
}
// Nothing has been overriden, so change the docshell itself.
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
LayoutDeviceIntSize size = docShellAsWin->GetSize();
size.height =
(CSSCoord(value) * CSSToDevScaleForBaseWindow(docShellAsWin)).Rounded();
aError = SetDocShellSize(size);
} }
CSSIntSize nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType, CSSIntSize nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType,
@@ -3657,11 +3655,19 @@ void nsGlobalWindowOuter::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
aIsWidth ? nullptr : &aLengthCSSPixels, aIsWidth ? nullptr : &aLengthCSSPixels,
aCallerType); aCallerType);
LayoutDeviceIntSize size = treeOwnerAsWin->GetSize();
auto scale = CSSToDevScaleForBaseWindow(treeOwnerAsWin); auto scale = CSSToDevScaleForBaseWindow(treeOwnerAsWin);
(aIsWidth ? size.width : size.height) = LayoutDeviceIntCoord value =
(CSSCoord(aLengthCSSPixels) * scale).Rounded(); (CSSCoord(CSSIntCoord(aLengthCSSPixels)) * scale).Rounded();
aError = treeOwnerAsWin->SetSize(size.width, size.height, true);
Maybe<LayoutDeviceIntCoord> width, height;
if (aIsWidth) {
width.emplace(value);
} else {
height.emplace(value);
}
aError = treeOwnerAsWin->SetDimensions(
{DimensionKind::Outer, Nothing(), Nothing(), width, height});
CheckForDPIChange(); CheckForDPIChange();
} }
@@ -3792,27 +3798,41 @@ float nsGlobalWindowOuter::GetMozInnerScreenYOuter(CallerType aCallerType) {
return nsPresContext::AppUnitsToFloatCSSPixels(r.y); return nsPresContext::AppUnitsToFloatCSSPixels(r.y);
} }
void nsGlobalWindowOuter::SetScreenXOuter(int32_t aScreenX, void nsGlobalWindowOuter::SetScreenCoord(int32_t aCoordCSSPixels, bool aIsX,
CallerType aCallerType, CallerType aCallerType,
ErrorResult& aError) { ErrorResult& aError) {
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow(); nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
if (!treeOwnerAsWin) { if (!treeOwnerAsWin) {
aError.Throw(NS_ERROR_FAILURE); aError.Throw(NS_ERROR_FAILURE);
return; return;
} }
LayoutDeviceIntPoint pos = treeOwnerAsWin->GetPosition(); CheckSecurityLeftAndTop(aIsX ? &aCoordCSSPixels : nullptr,
aIsX ? nullptr : &aCoordCSSPixels, aCallerType);
CheckSecurityLeftAndTop(&aScreenX, nullptr, aCallerType); auto scale = CSSToDevScaleForBaseWindow(treeOwnerAsWin);
LayoutDeviceIntCoord coord =
(CSSCoord(CSSIntCoord(aCoordCSSPixels)) * scale).Rounded();
pos.x = (CSSCoord(aScreenX) * CSSToDevScaleForBaseWindow(treeOwnerAsWin)) Maybe<LayoutDeviceIntCoord> x, y;
.Rounded(); if (aIsX) {
x.emplace(coord);
} else {
y.emplace(coord);
}
aError = treeOwnerAsWin->SetPosition(pos.x, pos.y); aError = treeOwnerAsWin->SetDimensions(
{DimensionKind::Outer, x, y, Nothing(), Nothing()});
CheckForDPIChange(); CheckForDPIChange();
} }
void nsGlobalWindowOuter::SetScreenXOuter(int32_t aScreenX,
CallerType aCallerType,
ErrorResult& aError) {
SetScreenCoord(aScreenX, /* aIsX */ true, aCallerType, aError);
}
int32_t nsGlobalWindowOuter::GetScreenYOuter(CallerType aCallerType, int32_t nsGlobalWindowOuter::GetScreenYOuter(CallerType aCallerType,
ErrorResult& aError) { ErrorResult& aError) {
return GetScreenXY(aCallerType, aError).y; return GetScreenXY(aCallerType, aError).y;
@@ -3821,19 +3841,7 @@ int32_t nsGlobalWindowOuter::GetScreenYOuter(CallerType aCallerType,
void nsGlobalWindowOuter::SetScreenYOuter(int32_t aScreenY, void nsGlobalWindowOuter::SetScreenYOuter(int32_t aScreenY,
CallerType aCallerType, CallerType aCallerType,
ErrorResult& aError) { ErrorResult& aError) {
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow(); SetScreenCoord(aScreenY, /* aIsX */ false, aCallerType, aError);
if (!treeOwnerAsWin) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
LayoutDeviceIntPoint pos = treeOwnerAsWin->GetPosition();
CheckSecurityLeftAndTop(nullptr, &aScreenY, aCallerType);
pos.y = (CSSCoord(aScreenY) * CSSToDevScaleForBaseWindow(treeOwnerAsWin))
.Rounded();
aError = treeOwnerAsWin->SetPosition(pos.x, pos.y);
CheckForDPIChange();
} }
// NOTE: Arguments to this function should have values scaled to // NOTE: Arguments to this function should have values scaled to
@@ -3862,22 +3870,6 @@ void nsGlobalWindowOuter::CheckSecurityWidthAndHeight(int32_t* aWidth,
} }
} }
// NOTE: Arguments to this function should have values in device pixels
nsresult nsGlobalWindowOuter::SetDocShellSize(
const LayoutDeviceIntSize& aSize) {
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocShell> docShell = mDocShell;
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
docShell->GetTreeOwner(getter_AddRefs(treeOwner));
NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(docShell, aSize.width, aSize.height),
NS_ERROR_FAILURE);
return NS_OK;
}
// NOTE: Arguments to this function should have values in app units // NOTE: Arguments to this function should have values in app units
void nsGlobalWindowOuter::SetCSSViewportWidthAndHeight(nscoord aInnerWidth, void nsGlobalWindowOuter::SetCSSViewportWidthAndHeight(nscoord aInnerWidth,
nscoord aInnerHeight) { nscoord aInnerHeight) {
@@ -5032,27 +5024,9 @@ void nsGlobalWindowOuter::BlurOuter(CallerType aCallerType) {
return; return;
} }
// If embedding apps don't implement nsIEmbeddingSiteWindow, we nsCOMPtr<nsIWebBrowserChrome> chrome = GetWebBrowserChrome();
// shouldn't throw exceptions to web content. if (chrome) {
chrome->Blur();
nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
nsCOMPtr<nsIEmbeddingSiteWindow> siteWindow(do_GetInterface(treeOwner));
if (siteWindow) {
// This method call may cause mDocShell to become nullptr.
siteWindow->Blur();
// if the root is focused, clear the focus
if (mDoc) {
if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
RefPtr<Element> element;
fm->GetFocusedElementForWindow(this, false, nullptr,
getter_AddRefs(element));
if (element == mDoc->GetRootElement()) {
OwningNonNull<nsGlobalWindowOuter> kungFuDeathGrip(*this);
fm->ClearFocus(kungFuDeathGrip);
}
}
}
} }
} }

View File

@@ -687,7 +687,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
double GetInnerWidthOuter(mozilla::ErrorResult& aError); double GetInnerWidthOuter(mozilla::ErrorResult& aError);
protected: protected:
nsresult GetInnerWidth(double* aWidth) override; nsresult GetInnerWidth(double* aInnerWidth) override;
void SetInnerWidthOuter(double aInnerWidth, void SetInnerWidthOuter(double aInnerWidth,
mozilla::dom::CallerType aCallerType, mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError); mozilla::ErrorResult& aError);
@@ -696,7 +696,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
double GetInnerHeightOuter(mozilla::ErrorResult& aError); double GetInnerHeightOuter(mozilla::ErrorResult& aError);
protected: protected:
nsresult GetInnerHeight(double* aHeight) override; nsresult GetInnerHeight(double* aInnerHeight) override;
void SetInnerHeightOuter(double aInnerHeight, void SetInnerHeightOuter(double aInnerHeight,
mozilla::dom::CallerType aCallerType, mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError); mozilla::ErrorResult& aError);
@@ -830,9 +830,6 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
// Outer windows only. // Outer windows only.
// Arguments to this function should have values in app units // Arguments to this function should have values in app units
void SetCSSViewportWidthAndHeight(nscoord width, nscoord height); void SetCSSViewportWidthAndHeight(nscoord width, nscoord height);
// Arguments to this function should have values in device pixels
MOZ_CAN_RUN_SCRIPT_BOUNDARY
nsresult SetDocShellSize(const mozilla::LayoutDeviceIntSize& aInnerSize);
static bool CanSetProperty(const char* aPrefName); static bool CanSetProperty(const char* aPrefName);
@@ -861,6 +858,12 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
void SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth, void SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
mozilla::dom::CallerType aCallerType, mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError); mozilla::ErrorResult& aError);
void SetInnerSize(int32_t aLengthCSSPixels, bool aIsWidth,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
void SetScreenCoord(int32_t aCoordCSSPixels, bool aIsX,
mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
nsRect GetInnerScreenRect(); nsRect GetInnerScreenRect();
static mozilla::Maybe<mozilla::CSSIntSize> GetRDMDeviceSize( static mozilla::Maybe<mozilla::CSSIntSize> GetRDMDeviceSize(
const Document& aDocument); const Document& aDocument);

View File

@@ -548,7 +548,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChild) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChild)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIWindowProvider) NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
@@ -585,20 +584,8 @@ BrowserChild::RemoteSizeShellTo(int32_t aWidth, int32_t aHeight,
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(ourDocShell)); nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(ourDocShell));
NS_ENSURE_STATE(docShellAsWin); NS_ENSURE_STATE(docShellAsWin);
int32_t width, height; bool sent =
docShellAsWin->GetSize(&width, &height); SendSizeShellTo(0, aWidth, aHeight, aShellItemWidth, aShellItemHeight);
uint32_t flags = 0;
if (width == aWidth) {
flags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX;
}
if (height == aHeight) {
flags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY;
}
bool sent = SendSizeShellTo(flags, aWidth, aHeight, aShellItemWidth,
aShellItemHeight);
return sent ? NS_OK : NS_ERROR_FAILURE; return sent ? NS_OK : NS_ERROR_FAILURE;
} }
@@ -656,47 +643,32 @@ BrowserChild::SetLinkStatus(const nsAString& aStatusText) {
} }
NS_IMETHODIMP NS_IMETHODIMP
BrowserChild::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY, BrowserChild::SetDimensions(DimensionRequest&& aRequest) {
int32_t aCx, int32_t aCy) {
// The parent is in charge of the dimension changes. If JS code wants to // The parent is in charge of the dimension changes. If JS code wants to
// change the dimensions (moveTo, screenX, etc.) we send a message to the // change the dimensions (moveTo, screenX, etc.) we send a message to the
// parent about the new requested dimension, the parent does the resize/move // parent about the new requested dimension, the parent does the resize/move
// then send a message to the child to update itself. For APIs like screenX // then send a message to the child to update itself. For APIs like screenX
// this function is called with the current value for the non-changed values. // this function is called with only the changed values. In a series of calls
// In a series of calls like window.screenX = 10; window.screenY = 10; for // like window.screenX = 10; window.screenY = 10; for the second call, since
// the second call, since screenX is not yet updated we might accidentally // screenX is not yet updated we might accidentally reset back screenX to it's
// reset back screenX to it's old value. To avoid this if a parameter did not // old value. To avoid this, if a parameter did not change, we want the parent
// change we want the parent to ignore its value. // to handle the unchanged values.
int32_t x, y, cx, cy;
GetDimensions(aFlags, &x, &y, &cx, &cy);
if (x == aX) {
aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_X;
}
if (y == aY) {
aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_Y;
}
if (cx == aCx) {
aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX;
}
if (cy == aCy) {
aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY;
}
double scale = mPuppetWidget ? mPuppetWidget->GetDefaultScale().scale : 1.0; double scale = mPuppetWidget ? mPuppetWidget->GetDefaultScale().scale : 1.0;
SendSetDimensions(aRequest, scale);
Unused << SendSetDimensions(aFlags, aX, aY, aCx, aCy, scale);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
BrowserChild::GetDimensions(uint32_t aFlags, int32_t* aX, int32_t* aY, BrowserChild::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aCx, int32_t* aCy) { int32_t* aY, int32_t* aCx, int32_t* aCy) {
ScreenIntRect rect = GetOuterRect(); ScreenIntRect rect = GetOuterRect();
if (aDimensionKind == DimensionKind::Inner) {
if (aX || aY) {
return NS_ERROR_NOT_IMPLEMENTED;
}
rect.SizeTo(GetInnerSize());
}
if (aX) { if (aX) {
*aX = rect.x; *aX = rect.x;
} }
@@ -709,43 +681,9 @@ BrowserChild::GetDimensions(uint32_t aFlags, int32_t* aX, int32_t* aY,
if (aCy) { if (aCy) {
*aCy = rect.height; *aCy = rect.height;
} }
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
BrowserChild::GetVisibility(bool* aVisibility) {
*aVisibility = true;
return NS_OK;
}
NS_IMETHODIMP
BrowserChild::SetVisibility(bool aVisibility) {
// should the platform support this? Bug 666365
return NS_OK;
}
NS_IMETHODIMP
BrowserChild::GetTitle(nsAString& aTitle) {
NS_WARNING("BrowserChild::GetTitle not supported in BrowserChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
BrowserChild::SetTitle(const nsAString& aTitle) {
// JavaScript sends the "DOMTitleChanged" event to the parent
// via the message manager.
return NS_OK;
}
NS_IMETHODIMP
BrowserChild::GetSiteWindow(void** aSiteWindow) {
NS_WARNING("BrowserChild::GetSiteWindow not supported in BrowserChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP NS_IMETHODIMP
BrowserChild::Blur() { return NS_ERROR_NOT_IMPLEMENTED; } BrowserChild::Blur() { return NS_ERROR_NOT_IMPLEMENTED; }
@@ -3273,7 +3211,7 @@ mozilla::ipc::IPCResult BrowserChild::RecvSafeAreaInsetsChanged(
// aSafeAreaInsets is for current screen. But we have to calculate // aSafeAreaInsets is for current screen. But we have to calculate
// safe insets for content window. // safe insets for content window.
int32_t x, y, cx, cy; int32_t x, y, cx, cy;
GetDimensions(0, &x, &y, &cx, &cy); GetDimensions(DimensionKind::Outer, &x, &y, &cx, &cy);
nsCOMPtr<nsIScreen> screen; nsCOMPtr<nsIScreen> screen;
screenMgr->ScreenForRect(x, y, cx, cy, getter_AddRefs(screen)); screenMgr->ScreenForRect(x, y, cx, cy, getter_AddRefs(screen));

View File

@@ -12,7 +12,6 @@
#include "nsIWebNavigation.h" #include "nsIWebNavigation.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIWebBrowserChrome.h" #include "nsIWebBrowserChrome.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIWebBrowserChromeFocus.h" #include "nsIWebBrowserChromeFocus.h"
#include "nsIDOMEventListener.h" #include "nsIDOMEventListener.h"
#include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestor.h"
@@ -141,7 +140,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
public ipc::MessageManagerCallback, public ipc::MessageManagerCallback,
public PBrowserChild, public PBrowserChild,
public nsIWebBrowserChrome, public nsIWebBrowserChrome,
public nsIEmbeddingSiteWindow,
public nsIWebBrowserChromeFocus, public nsIWebBrowserChromeFocus,
public nsIInterfaceRequestor, public nsIInterfaceRequestor,
public nsIWindowProvider, public nsIWindowProvider,
@@ -199,7 +197,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIWEBBROWSERCHROME NS_DECL_NSIWEBBROWSERCHROME
NS_DECL_NSIEMBEDDINGSITEWINDOW
NS_DECL_NSIWEBBROWSERCHROMEFOCUS NS_DECL_NSIWEBBROWSERCHROMEFOCUS
NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIWINDOWPROVIDER NS_DECL_NSIWINDOWPROVIDER

View File

@@ -821,20 +821,9 @@ mozilla::ipc::IPCResult BrowserParent::RecvSizeShellTo(
nsresult rv = docShell->GetTreeOwner(getter_AddRefs(treeOwner)); nsresult rv = docShell->GetTreeOwner(getter_AddRefs(treeOwner));
NS_ENSURE_SUCCESS(rv, IPC_OK()); NS_ENSURE_SUCCESS(rv, IPC_OK());
int32_t width = aWidth;
int32_t height = aHeight;
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX) {
width = mDimensions.width;
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY) {
height = mDimensions.height;
}
nsCOMPtr<nsIAppWindow> appWin(do_GetInterface(treeOwner)); nsCOMPtr<nsIAppWindow> appWin(do_GetInterface(treeOwner));
NS_ENSURE_TRUE(appWin, IPC_OK()); NS_ENSURE_TRUE(appWin, IPC_OK());
appWin->SizeShellToWithLimit(width, height, aShellItemWidth, appWin->SizeShellToWithLimit(aWidth, aHeight, aShellItemWidth,
aShellItemHeight); aShellItemHeight);
return IPC_OK(); return IPC_OK();
@@ -977,11 +966,7 @@ bool BrowserParent::Show(const OwnerShowInfo& aOwnerInfo) {
} }
mozilla::ipc::IPCResult BrowserParent::RecvSetDimensions( mozilla::ipc::IPCResult BrowserParent::RecvSetDimensions(
const uint32_t& aFlags, const int32_t& aX, const int32_t& aY, mozilla::DimensionRequest aRequest, const double& aScale) {
const int32_t& aCx, const int32_t& aCy, const double& aScale) {
MOZ_ASSERT(!(aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER),
"We should never see DIM_FLAGS_SIZE_INNER here!");
NS_ENSURE_TRUE(mFrameElement, IPC_OK()); NS_ENSURE_TRUE(mFrameElement, IPC_OK());
nsCOMPtr<nsIDocShell> docShell = mFrameElement->OwnerDoc()->GetDocShell(); nsCOMPtr<nsIDocShell> docShell = mFrameElement->OwnerDoc()->GetDocShell();
NS_ENSURE_TRUE(docShell, IPC_OK()); NS_ENSURE_TRUE(docShell, IPC_OK());
@@ -990,8 +975,8 @@ mozilla::ipc::IPCResult BrowserParent::RecvSetDimensions(
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = do_QueryInterface(treeOwner); nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = do_QueryInterface(treeOwner);
NS_ENSURE_TRUE(treeOwnerAsWin, IPC_OK()); NS_ENSURE_TRUE(treeOwnerAsWin, IPC_OK());
// We only care about the parameters that actually changed, see more details // `BrowserChild` only sends the values to actually be changed, see more
// in `BrowserChild::SetDimensions()`. // details in `BrowserChild::SetDimensions()`.
// Note that `BrowserChild::SetDimensions()` may be called before receiving // Note that `BrowserChild::SetDimensions()` may be called before receiving
// our `SendUIResolutionChanged()` call. Therefore, if given each coordinate // our `SendUIResolutionChanged()` call. Therefore, if given each coordinate
// shouldn't be ignored, we need to recompute it if DPI has been changed. // shouldn't be ignored, we need to recompute it if DPI has been changed.
@@ -1000,62 +985,26 @@ mozilla::ipc::IPCResult BrowserParent::RecvSetDimensions(
// NOTE(emilio): We use GetWidgetCSSToDeviceScale() because the old scale is a // NOTE(emilio): We use GetWidgetCSSToDeviceScale() because the old scale is a
// widget scale, and we only use the current scale to scale up/down the // widget scale, and we only use the current scale to scale up/down the
// relevant values. // relevant values.
double currentScale = treeOwnerAsWin->GetWidgetCSSToDeviceScale();
int32_t x = aX; CSSToLayoutDeviceScale oldScale((float)aScale);
int32_t y = aY; CSSToLayoutDeviceScale currentScale(
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) { (float)treeOwnerAsWin->GetWidgetCSSToDeviceScale());
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_X) {
int32_t unused;
treeOwnerAsWin->GetPosition(&x, &unused);
} else if (aScale != currentScale) {
x = x * currentScale / aScale;
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_Y) { if (oldScale != currentScale) {
int32_t unused; auto rescaleFunc = [&oldScale, &currentScale](LayoutDeviceIntCoord& aVal) {
treeOwnerAsWin->GetPosition(&unused, &y); aVal = (LayoutDeviceCoord(aVal) / oldScale * currentScale).Rounded();
} else if (aScale != currentScale) { };
y = y * currentScale / aScale; aRequest.mX.apply(rescaleFunc);
} aRequest.mY.apply(rescaleFunc);
aRequest.mWidth.apply(rescaleFunc);
aRequest.mHeight.apply(rescaleFunc);
} }
int32_t cx = aCx; // treeOwner is the chrome tree owner, but we wan't the content tree owner.
int32_t cy = aCy; nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = do_GetInterface(treeOwner);
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) { NS_ENSURE_TRUE(webBrowserChrome, IPC_OK());
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX) { webBrowserChrome->SetDimensions(std::move(aRequest));
int32_t unused; return IPC_OK();
treeOwnerAsWin->GetSize(&cx, &unused);
} else if (aScale != currentScale) {
cx = cx * currentScale / aScale;
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY) {
int32_t unused;
treeOwnerAsWin->GetSize(&unused, &cy);
} else if (aScale != currentScale) {
cy = cy * currentScale / aScale;
}
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
treeOwnerAsWin->SetPositionAndSize(x, y, cx, cy, nsIBaseWindow::eRepaint);
return IPC_OK();
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
treeOwnerAsWin->SetPosition(x, y);
return IPC_OK();
}
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
treeOwnerAsWin->SetSize(cx, cy, true);
return IPC_OK();
}
MOZ_ASSERT(false, "Unknown flags!");
return IPC_FAIL_NO_REASON(this);
} }
nsresult BrowserParent::UpdatePosition() { nsresult BrowserParent::UpdatePosition() {

View File

@@ -737,9 +737,8 @@ class BrowserParent final : public PBrowserParent,
mozilla::ipc::IPCResult RecvPaintWhileInterruptingJSNoOp( mozilla::ipc::IPCResult RecvPaintWhileInterruptingJSNoOp(
const LayersObserverEpoch& aEpoch); const LayersObserverEpoch& aEpoch);
mozilla::ipc::IPCResult RecvSetDimensions( mozilla::ipc::IPCResult RecvSetDimensions(mozilla::DimensionRequest aRequest,
const uint32_t& aFlags, const int32_t& aX, const int32_t& aY, const double& aScale);
const int32_t& aCx, const int32_t& aCy, const double& aScale);
mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt( mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt(
const nsCString& aOrigin, const bool& aHideDoorHanger); const nsCString& aOrigin, const bool& aHideDoorHanger);

View File

@@ -83,6 +83,7 @@ using nsIWidget::TouchPointerState from "nsIWidget.h";
using nsIWidget::TouchpadGesturePhase from "nsIWidget.h"; using nsIWidget::TouchpadGesturePhase from "nsIWidget.h";
using nsCursor from "nsIWidget.h"; using nsCursor from "nsIWidget.h";
using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h"; using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
using struct mozilla::DimensionRequest from "mozilla/widget/WidgetMessageUtils.h";
using class mozilla::dom::MessagePort from "mozilla/dom/MessagePort.h"; using class mozilla::dom::MessagePort from "mozilla/dom/MessagePort.h";
using class mozilla::dom::ipc::StructuredCloneData from "mozilla/dom/ipc/StructuredCloneData.h"; using class mozilla::dom::ipc::StructuredCloneData from "mozilla/dom/ipc/StructuredCloneData.h";
using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h"; using mozilla::dom::MaybeDiscardedWindowContext from "mozilla/dom/WindowContext.h";
@@ -622,10 +623,14 @@ parent:
/** /**
* Sent by the child to the parent to inform it that an update to the * Sent by the child to the parent to inform it that an update to the
* dimensions has been requested, likely through win.moveTo or resizeTo * dimensions has been requested.
*
* @param aRequest The requested change of inner or outer dimensions.
* @param aScale The scale at the time of the request. This is to allow
* the parent to recompute the dimensions in case of an
* ongoing scale change.
*/ */
async SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY, async SetDimensions(DimensionRequest aRequest, double aScale);
int32_t aCx, int32_t aCy, double aScale);
[Nested=inside_sync] sync DispatchWheelEvent(WidgetWheelEvent event); [Nested=inside_sync] sync DispatchWheelEvent(WidgetWheelEvent event);
[Nested=inside_sync] sync DispatchMouseEvent(WidgetMouseEvent event); [Nested=inside_sync] sync DispatchMouseEvent(WidgetMouseEvent event);

View File

@@ -10,7 +10,6 @@ with Files("**"):
DIRS += ["build"] DIRS += ["build"]
XPIDL_SOURCES += [ XPIDL_SOURCES += [
"nsIEmbeddingSiteWindow.idl",
"nsIWebBrowser.idl", "nsIWebBrowser.idl",
"nsIWebBrowserChrome.idl", "nsIWebBrowserChrome.idl",
"nsIWebBrowserChromeFocus.idl", "nsIWebBrowserChromeFocus.idl",

View File

@@ -1,152 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
/* THIS IS A PUBLIC EMBEDDING API */
/**
* The nsIEmbeddingSiteWindow is implemented by the embedder to provide
* Gecko with the means to call up to the host to resize the window,
* hide or show it and set/get its title.
*/
[scriptable, uuid(0b976267-4aaa-4f36-a2d4-27b5ca8d73bb)]
interface nsIEmbeddingSiteWindow : nsISupports
{
/**
* Flag indicates that position of the top left corner of the outer area
* is required/specified.
*
* @see setDimensions
* @see getDimensions
*/
const unsigned long DIM_FLAGS_POSITION = 1;
/**
* Flag indicates that the size of the inner area is required/specified.
*
* @note The inner and outer flags are mutually exclusive and it is
* invalid to combine them.
*
* @see setDimensions
* @see getDimensions
* @see DIM_FLAGS_SIZE_OUTER
*/
const unsigned long DIM_FLAGS_SIZE_INNER = 2;
/**
* Flag indicates that the size of the outer area is required/specified.
*
* @see setDimensions
* @see getDimensions
* @see DIM_FLAGS_SIZE_INNER
*/
const unsigned long DIM_FLAGS_SIZE_OUTER = 4;
/**
* Flag indicates that the x parameter should be ignored.
*
* @see setDimensions
*/
const unsigned long DIM_FLAGS_IGNORE_X = 8;
/**
* Flag indicates that the y parameter should be ignored.
*
* @see setDimensions
*/
const unsigned long DIM_FLAGS_IGNORE_Y = 16;
/**
* Flag indicates that the cx parameter should be ignored.
*
* @see setDimensions
*/
const unsigned long DIM_FLAGS_IGNORE_CX = 32;
/**
* Flag indicates that the cy parameter should be ignored.
*
* @see setDimensions
*/
const unsigned long DIM_FLAGS_IGNORE_CY = 64;
/**
* Sets the dimensions for the window; the position & size. The
* flags to indicate what the caller wants to set and whether the size
* refers to the inner or outer area. The inner area refers to just
* the embedded area, wheras the outer area can also include any
* surrounding chrome, window frame, title bar, and so on.
*
* @param flags Combination of position, inner and outer size flags.
* The ignore flags are telling the parent to use the
* current values for those dimensions and ignore the
* corresponding parameters the child sends.
* @param x Left hand corner of the outer area.
* @param y Top corner of the outer area.
* @param cx Width of the inner or outer area.
* @param cy Height of the inner or outer area.
*
* @return <code>NS_OK</code> if operation was performed correctly;
* <code>NS_ERROR_UNEXPECTED</code> if window could not be
* destroyed;
* <code>NS_ERROR_INVALID_ARG</code> for bad flag combination
* or illegal dimensions.
*
* @see getDimensions
* @see DIM_FLAGS_POSITION
* @see DIM_FLAGS_SIZE_OUTER
* @see DIM_FLAGS_SIZE_INNER
*/
void setDimensions(in unsigned long flags, in long x, in long y, in long cx, in long cy);
/**
* Gets the dimensions of the window. The caller may pass
* <CODE>nullptr</CODE> for any value it is uninterested in receiving.
*
* @param flags Combination of position, inner and outer size flag .
* @param x Left hand corner of the outer area; or <CODE>nullptr</CODE>.
* @param y Top corner of the outer area; or <CODE>nullptr</CODE>.
* @param cx Width of the inner or outer area; or <CODE>nullptr</CODE>.
* @param cy Height of the inner or outer area; or <CODE>nullptr</CODE>.
*
* @see setDimensions
* @see DIM_FLAGS_POSITION
* @see DIM_FLAGS_SIZE_OUTER
* @see DIM_FLAGS_SIZE_INNER
*/
void getDimensions(in unsigned long flags, out long x, out long y, out long cx, out long cy);
/**
* Visibility of the window.
*/
attribute boolean visibility;
/**
* Title of the window.
*/
attribute AString title;
/**
* Native window for the site's window. The implementor should copy the
* native window object into the address supplied by the caller. The
* type of the native window that the address refers to is platform
* and OS specific as follows:
*
* <ul>
* <li>On Win32 it is an <CODE>HWND</CODE>.</li>
* <li>On MacOS this is a <CODE>WindowPtr</CODE>.</li>
* <li>On GTK this is a <CODE>GtkWidget*</CODE>.</li>
* </ul>
*/
[noscript] readonly attribute voidPtr siteWindow;
/**
* Blur the window. This should unfocus the window and send an onblur event.
*/
void blur();
};

View File

@@ -37,8 +37,6 @@ interface nsIWebBrowser : nsISupports
* this property to point to the chrome object before creating the browser * this property to point to the chrome object before creating the browser
* window via the browser's <CODE>nsIBaseWindow</CODE> interface. * window via the browser's <CODE>nsIBaseWindow</CODE> interface.
* *
* The chrome object must also implement <CODE>nsIEmbeddingSiteWindow</CODE>.
*
* The chrome may optionally implement <CODE>nsIInterfaceRequestor</CODE>, * The chrome may optionally implement <CODE>nsIInterfaceRequestor</CODE>,
* <CODE>nsIWebBrowserChromeFocus</CODE>, * <CODE>nsIWebBrowserChromeFocus</CODE>,
* <CODE>nsIContextMenuListener</CODE> and * <CODE>nsIContextMenuListener</CODE> and
@@ -58,7 +56,6 @@ interface nsIWebBrowser : nsISupports
* *
* @see nsIBaseWindow * @see nsIBaseWindow
* @see nsIWebBrowserChrome * @see nsIWebBrowserChrome
* @see nsIEmbeddingSiteWindow
* @see nsIInterfaceRequestor * @see nsIInterfaceRequestor
* @see nsIWebBrowserChromeFocus * @see nsIWebBrowserChromeFocus
* @see nsIContextMenuListener * @see nsIContextMenuListener

View File

@@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl" #include "nsISupports.idl"
#include "nsIBaseWindow.idl"
interface nsIWebBrowser; interface nsIWebBrowser;
interface nsIDocShellTreeItem; interface nsIDocShellTreeItem;
@@ -113,4 +114,29 @@ interface nsIWebBrowserChrome : nsISupports
* @return true if it's a modal window * @return true if it's a modal window
*/ */
boolean isWindowModal(); boolean isWindowModal();
/**
* Allows to request the change of individual dimensions of a window
* without specifying all dimensions.
*
* Gets called as fallback when no nsIBaseWindow is available.
*
* @see nsIBaseWindow
*/
void setDimensions(in DimensionRequest aRequest);
/**
* Gets the dimensions of the window. The caller may pass
* <CODE>nullptr</CODE> for any value it is uninterested in receiving.
*
* Gets called as fallback when no nsIBaseWindow is available.
*
* @see nsIBaseWindow
*/
void getDimensions(in DimensionKind aDimensionKind, out long aX, out long aY, out long aCX, out long aCY);
/**
* Blur the window. This should unfocus the window and send an onblur event.
*/
void blur();
}; };

View File

@@ -956,12 +956,22 @@ nsWebBrowser::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aCX,
*aCY = bounds.Height(); *aCY = bounds.Height();
} }
return NS_OK; return NS_OK;
} else {
// Can directly return this as it is the
// same interface, thus same returns.
return mDocShell->GetPositionAndSize(aX, aY, aCX, aCY);
} }
return NS_OK;
// Can directly return this as it is the
// same interface, thus same returns.
return mDocShell->GetPositionAndSize(aX, aY, aCX, aCY);
}
NS_IMETHODIMP
nsWebBrowser::SetDimensions(DimensionRequest&& aRequest) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsWebBrowser::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
return NS_ERROR_NOT_IMPLEMENTED;
} }
NS_IMETHODIMP NS_IMETHODIMP

View File

@@ -21,26 +21,28 @@ function closeEnough(actual, expected) {
} }
async function resizeWindow(x, y) { async function resizeWindow(x, y) {
window.innerWidth = x; // For Linux we have to change only one dimension at a time. (Bug 1803611)
window.innerHeight = y; if (window.innerWidth != x) {
let resizePromise = BrowserTestUtils.waitForEvent(window, "resize");
window.innerWidth = x;
await resizePromise;
}
if (window.innerHeight != y) {
let resizePromise = BrowserTestUtils.waitForEvent(window, "resize");
window.innerHeight = y;
await resizePromise;
}
await waitForAnimationFrames(); await waitForAnimationFrames();
await TestUtils.waitForCondition( ok(
() => { closeEnough(window.innerWidth, x),
info(`window is ${window.innerWidth} x ${window.innerHeight}`); `Window innerWidth ${window.innerWidth} is close enough to ${x}`
if ( );
closeEnough(window.innerWidth, x) && ok(
closeEnough(window.innerHeight, y) closeEnough(window.innerHeight, y),
) { `Window innerHeight ${window.innerHeight} is close enough to ${y}`
return true;
}
window.innerWidth = x;
window.innerHeight = y;
return false;
},
`Wait for ${x}x${y}`,
250
); );
} }
@@ -97,6 +99,33 @@ async function checkPreviewNavigationVisibility(expected) {
} }
add_task(async function testResizing() { add_task(async function testResizing() {
if (window.windowState != window.STATE_NORMAL) {
todo_is(
window.windowState,
window.STATE_NORMAL,
"windowState should be STATE_NORMAL"
);
// On Windows the size of the window decoration depends on the size mode.
// Trying to set the inner size of a maximized window changes the size mode
// but calculates the new window size with the maximized window
// decorations. On Linux a maximized window can also cause problems when
// the window was maximized recently and the corresponding resize event is
// still outstanding.
window.restore();
// On Linux we would have to wait for the resize event here, but the
// restored and maximized size can also be equal. Brute forcing a resize
// to a specific size works around that.
await BrowserTestUtils.waitForCondition(async () => {
let width = window.screen.availWidth * 0.75;
let height = window.screen.availHeight * 0.75;
window.resizeTo(width, height);
return (
closeEnough(window.outerWidth, width) &&
closeEnough(window.outerHeight, height)
);
});
}
await PrintHelper.withTestPage(async helper => { await PrintHelper.withTestPage(async helper => {
let { innerWidth, innerHeight } = window; let { innerWidth, innerHeight } = window;

119
widget/DimensionRequest.cpp Normal file
View File

@@ -0,0 +1,119 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DimensionRequest.h"
#include "nsIBaseWindow.h"
#include "nsIDocShellTreeOwner.h"
namespace mozilla {
nsresult DimensionRequest::SupplementFrom(nsIBaseWindow* aSource) {
NS_ENSURE_ARG_POINTER(aSource);
int32_t x = 0, y = 0, width = 0, height = 0;
bool needsPosition = mX.isSome() != mY.isSome();
bool needsSize = mWidth.isSome() != mHeight.isSome();
if (!needsPosition && !needsSize) {
return NS_OK;
}
MOZ_TRY(aSource->GetDimensions(mDimensionKind, needsPosition ? &x : nullptr,
needsPosition ? &y : nullptr,
needsSize ? &width : nullptr,
needsSize ? &height : nullptr));
if (needsPosition) {
if (mX.isNothing()) {
mX.emplace(x);
}
if (mY.isNothing()) {
mY.emplace(y);
}
}
if (needsSize) {
if (mWidth.isNothing()) {
mWidth.emplace(width);
}
if (mHeight.isNothing()) {
mHeight.emplace(height);
}
}
MOZ_ASSERT(mX.isSome() == mY.isSome());
MOZ_ASSERT(mWidth.isSome() == mHeight.isSome());
return NS_OK;
}
nsresult DimensionRequest::ApplyOuterTo(nsIBaseWindow* aTarget) {
NS_ENSURE_ARG_POINTER(aTarget);
MOZ_ASSERT(mX.isSome() == mY.isSome(),
"Missing dimensions should have been completed.");
MOZ_ASSERT(mWidth.isSome() == mHeight.isSome(),
"Missing dimensions should have been completed.");
if (mDimensionKind != DimensionKind::Outer) {
MOZ_ASSERT_UNREACHABLE("Expected outer dimensions.");
return NS_ERROR_UNEXPECTED;
}
bool havePosition = mX.isSome() && mY.isSome();
bool haveSize = mWidth.isSome() && mHeight.isSome();
if (!havePosition && !haveSize) {
return NS_OK;
}
if (havePosition && haveSize) {
return aTarget->SetPositionAndSize(*mX, *mY, *mWidth, *mHeight, true);
}
if (havePosition) {
return aTarget->SetPosition(*mX, *mY);
}
if (haveSize) {
return aTarget->SetSize(*mWidth, *mHeight, true);
}
MOZ_ASSERT_UNREACHABLE();
return NS_ERROR_UNEXPECTED;
}
nsresult DimensionRequest::ApplyInnerTo(nsIDocShellTreeOwner* aTarget,
bool aAsRootShell) {
NS_ENSURE_ARG_POINTER(aTarget);
MOZ_ASSERT(mX.isSome() == mY.isSome(),
"Missing dimensions should have been completed.");
MOZ_ASSERT(mWidth.isSome() == mHeight.isSome(),
"Missing dimensions should have been completed.");
if (mDimensionKind != DimensionKind::Inner) {
MOZ_ASSERT_UNREACHABLE("Expected inner dimensions.");
return NS_ERROR_UNEXPECTED;
}
bool havePosition = mX.isSome() && mY.isSome();
bool haveSize = mWidth.isSome() && mHeight.isSome();
if (!havePosition && !haveSize) {
return NS_OK;
}
if (havePosition) {
MOZ_ASSERT_UNREACHABLE("Inner position is not implemented.");
return NS_ERROR_NOT_IMPLEMENTED;
}
if (haveSize) {
if (aAsRootShell) {
return aTarget->SetRootShellSize(*mWidth, *mHeight);
}
return aTarget->SetPrimaryContentSize(*mWidth, *mHeight);
}
MOZ_ASSERT_UNREACHABLE();
return NS_ERROR_UNEXPECTED;
}
} // namespace mozilla

71
widget/DimensionRequest.h Normal file
View File

@@ -0,0 +1,71 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_DimensionRequest_h
#define mozilla_DimensionRequest_h
#include "Units.h"
#include "mozilla/Maybe.h"
class nsIBaseWindow;
class nsIDocShellTreeOwner;
namespace mozilla {
enum class DimensionKind { Inner, Outer };
/**
* DimensionRequest allows to request the change of some dimensions without
* having to specify the unchanged dimensions. This is specifically necessary
* when a change is initiated from a child process, which might not have an
* up-to-date view of its latest dimensions. Having to specify the missing
* dimensions with an outdated view can revert a previous change.
*
* The following series of changes `window.screenX = 10; window.screenY = 10;`
* essentially translates into two moveTo() calls. For the second call we want
* to account for changes made by the first call. From a child process we would
* end up crafting the second call without knowing the results of the first
* call. In the parent process we have access to results of the first call
* before crafting the second one. Although on Linux even the parent process
* doesn't have immediate access to the results of the last change.
*
* Note: The concept of an inner position is not present on
* nsIDocShellTreeOwner and nsIBaseWindow. A request specifying an inner
* position will return an NS_ERROR_NOT_IMPLEMENTED.
*/
struct DimensionRequest {
DimensionKind mDimensionKind;
Maybe<LayoutDeviceIntCoord> mX;
Maybe<LayoutDeviceIntCoord> mY;
Maybe<LayoutDeviceIntCoord> mWidth;
Maybe<LayoutDeviceIntCoord> mHeight;
/**
* Fills the missing dimensions with values obtained from `aSource`. Whether
* inner dimensions are supported depends on the implementation of
* `nsIBaseWindow::GetDimensions` for `aSource`.
*
* @param aSource The source for the missing dimensions.
*/
nsresult SupplementFrom(nsIBaseWindow* aSource);
/**
* Changes the outer size and or position of `aTarget`. Only outer dimensions
* are supported.
*
* @param aTarget The target whose size or position we want to change.
*/
nsresult ApplyOuterTo(nsIBaseWindow* aTarget);
/**
* Changes the inner size of `aTarget`. Only inner dimensions are supported.
*
* @param aTarget The target whose size we want to change.
*/
nsresult ApplyInnerTo(nsIDocShellTreeOwner* aTarget, bool aAsRootShell);
};
} // namespace mozilla
#endif // mozilla_DimensionRequest_h

View File

@@ -1021,9 +1021,9 @@ LayoutDeviceIntPoint PuppetWidget::GetWindowPosition() {
} }
int32_t winX, winY, winW, winH; int32_t winX, winY, winW, winH;
NS_ENSURE_SUCCESS( NS_ENSURE_SUCCESS(GetOwningBrowserChild()->GetDimensions(
GetOwningBrowserChild()->GetDimensions(0, &winX, &winY, &winW, &winH), DimensionKind::Outer, &winX, &winY, &winW, &winH),
LayoutDeviceIntPoint()); LayoutDeviceIntPoint());
return LayoutDeviceIntPoint(winX, winY) + return LayoutDeviceIntPoint(winX, winY) +
GetOwningBrowserChild()->GetClientOffset(); GetOwningBrowserChild()->GetClientOffset();
} }

View File

@@ -7,6 +7,7 @@
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsNativeTheme.h" #include "nsNativeTheme.h"
#include "mozilla/StaticPrefs_widget.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::widget; using namespace mozilla::widget;

View File

@@ -7,6 +7,7 @@
#include "ipc/EnumSerializer.h" #include "ipc/EnumSerializer.h"
#include "ipc/IPCMessageUtils.h" #include "ipc/IPCMessageUtils.h"
#include "mozilla/DimensionRequest.h"
#include "mozilla/LookAndFeel.h" #include "mozilla/LookAndFeel.h"
#include "mozilla/widget/ThemeChangeKind.h" #include "mozilla/widget/ThemeChangeKind.h"
#include "nsIWidget.h" #include "nsIWidget.h"
@@ -57,6 +58,16 @@ struct ParamTraits<nsIWidget::TouchPointerState>
: public BitFlagsEnumSerializer<nsIWidget::TouchPointerState, : public BitFlagsEnumSerializer<nsIWidget::TouchPointerState,
nsIWidget::TouchPointerState::ALL_BITS> {}; nsIWidget::TouchPointerState::ALL_BITS> {};
template <>
struct ParamTraits<mozilla::DimensionKind>
: public ContiguousEnumSerializerInclusive<mozilla::DimensionKind,
mozilla::DimensionKind::Inner,
mozilla::DimensionKind::Outer> {
};
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::DimensionRequest, mDimensionKind, mX,
mY, mWidth, mHeight);
} // namespace IPC } // namespace IPC
#endif // WidgetMessageUtils_h #endif // WidgetMessageUtils_h

View File

@@ -171,6 +171,7 @@ EXPORTS.mozilla += [
"ContentCache.h", "ContentCache.h",
"ContentData.h", "ContentData.h",
"ContentEvents.h", "ContentEvents.h",
"DimensionRequest.h",
"EventClassList.h", "EventClassList.h",
"EventForwards.h", "EventForwards.h",
"EventMessageList.h", "EventMessageList.h",
@@ -214,6 +215,7 @@ UNIFIED_SOURCES += [
"CompositorWidget.cpp", "CompositorWidget.cpp",
"ContentCache.cpp", "ContentCache.cpp",
"ContentData.cpp", "ContentData.cpp",
"DimensionRequest.cpp",
"GfxDriverInfo.cpp", "GfxDriverInfo.cpp",
"GfxInfoBase.cpp", "GfxInfoBase.cpp",
"GfxInfoCollector.cpp", "GfxInfoCollector.cpp",

View File

@@ -11,11 +11,14 @@
[ptr] native nsIWidget(nsIWidget); [ptr] native nsIWidget(nsIWidget);
%{C++ %{C++
#include "Units.h" #include "Units.h"
#include "mozilla/DimensionRequest.h"
class nsIWidget; class nsIWidget;
%} %}
typedef voidPtr nativeWindow; typedef voidPtr nativeWindow;
native DimensionRequest(mozilla::DimensionRequest&&);
native DimensionKind(mozilla::DimensionKind);
/** /**
* The nsIBaseWindow describes a generic window and basic operations that * The nsIBaseWindow describes a generic window and basic operations that
@@ -146,6 +149,37 @@ interface nsIBaseWindow : nsISupports
} }
%} %}
/**
* Allows to request the change of individual dimensions without specifying
* the other components.
*
* @param aRequest - The requested change. A request to change only the width
* may look like:
* {DimensionKind::Outer, Nothing(), Nothing(), Some(20), Nothing()}
*
* Note: Inner position is not supported.
*
* @see DimensionRequest
*/
void setDimensions(in DimensionRequest aRequest);
/**
* Gets the dimensions of the window. The caller may pass nullptr for any
* value it is uninterested in receiving.
*
* @param aDimensionKind Specifies whether the dimensions are in reference
* to the inner or outer dimensions.
* @param aX Left hand corner of the outer area; or nullptr.
* @param aY Top corner of the outer area; or nullptr.
* @param aCX Width of the inner or outer area; or nullptr.
* @param aCY Height of the inner or outer area; or nullptr.
*
* Note: Inner position is not supported.
*
* @see DimensionRequest
*/
void getDimensions(in DimensionKind aDimensionKind, out long aX, out long aY, out long aCX, out long aCY);
/** /**
* Tell the window to repaint itself * Tell the window to repaint itself
* @param aForce - if true, repaint immediately * @param aForce - if true, repaint immediately

View File

@@ -11,7 +11,6 @@
#include "nsIBrowserChild.h" #include "nsIBrowserChild.h"
#include "nsIDialogParamBlock.h" #include "nsIDialogParamBlock.h"
#include "nsIDocShell.h" #include "nsIDocShell.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIInterfaceRequestorUtils.h" #include "nsIInterfaceRequestorUtils.h"
#include "nsIPrintSettings.h" #include "nsIPrintSettings.h"
#include "nsIWebBrowserChrome.h" #include "nsIWebBrowserChrome.h"
@@ -155,10 +154,10 @@ HWND nsPrintDialogServiceWin::GetHWNDForDOMWindow(mozIDOMWindowProxy* aWindow) {
} }
if (chrome) { if (chrome) {
nsCOMPtr<nsIEmbeddingSiteWindow> site(do_QueryInterface(chrome)); nsCOMPtr<nsIBaseWindow> site(do_QueryInterface(chrome));
if (site) { if (site) {
HWND w; HWND w;
site->GetSiteWindow(reinterpret_cast<void**>(&w)); site->GetParentNativeWindow(reinterpret_cast<void**>(&w));
return w; return w;
} }
} }

View File

@@ -29,7 +29,6 @@
#include "mozilla/dom/Document.h" #include "mozilla/dom/Document.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "nsScreen.h" #include "nsScreen.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h" #include "nsIInterfaceRequestorUtils.h"
#include "nsIIOService.h" #include "nsIIOService.h"
@@ -284,13 +283,9 @@ NS_IMETHODIMP AppWindow::GetInterface(const nsIID& aIID, void** aSink) {
} }
if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome)) && if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome)) &&
NS_SUCCEEDED(EnsureContentTreeOwner()) && NS_SUCCEEDED(EnsureContentTreeOwner()) &&
NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink))) NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink))) {
return NS_OK;
if (aIID.Equals(NS_GET_IID(nsIEmbeddingSiteWindow)) &&
NS_SUCCEEDED(EnsureContentTreeOwner()) &&
NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink)))
return NS_OK; return NS_OK;
}
return QueryInterface(aIID, aSink); return QueryInterface(aIID, aSink);
} }
@@ -791,6 +786,23 @@ NS_IMETHODIMP AppWindow::GetPositionAndSize(int32_t* x, int32_t* y, int32_t* cx,
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
AppWindow::SetDimensions(DimensionRequest&& aRequest) {
// For the chrome the inner size is the root shell size, and for the content
// it's the primary content size. We lack an indicator here that would allow
// us to distinguish between the two.
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
AppWindow::GetDimensions(DimensionKind aDimensionKind, int32_t* aX, int32_t* aY,
int32_t* aCX, int32_t* aCY) {
// For the chrome the inner size is the root shell size, and for the content
// it's the primary content size. We lack an indicator here that would allow
// us to distinguish between the two.
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP AppWindow::Center(nsIAppWindow* aRelative, bool aScreen, NS_IMETHODIMP AppWindow::Center(nsIAppWindow* aRelative, bool aScreen,
bool aAlert) { bool aAlert) {
DesktopIntRect rect; DesktopIntRect rect;

View File

@@ -17,7 +17,6 @@
#include "nsWidgetInitData.h" #include "nsWidgetInitData.h"
#include "nsWidgetsCID.h" #include "nsWidgetsCID.h"
#include "nsIWidget.h" #include "nsIWidget.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsAppDirectoryServiceDefs.h" #include "nsAppDirectoryServiceDefs.h"
#include "nsAppShellService.h" #include "nsAppShellService.h"
@@ -195,12 +194,11 @@ nsAppShellService::CreateTopLevelWindow(nsIAppWindow* aParent, nsIURI* aUrl,
* by nsAppShellService::CreateWindowlessBrowser * by nsAppShellService::CreateWindowlessBrowser
*/ */
class WebBrowserChrome2Stub final : public nsIWebBrowserChrome, class WebBrowserChrome2Stub final : public nsIWebBrowserChrome,
public nsIEmbeddingSiteWindow,
public nsIInterfaceRequestor, public nsIInterfaceRequestor,
public nsSupportsWeakReference { public nsSupportsWeakReference {
protected: protected:
nsCOMPtr<nsIWebBrowser> mBrowser; nsCOMPtr<nsIWebBrowser> mBrowser;
virtual ~WebBrowserChrome2Stub() {} virtual ~WebBrowserChrome2Stub() = default;
public: public:
void SetBrowser(nsIWebBrowser* aBrowser) { mBrowser = aBrowser; } void SetBrowser(nsIWebBrowser* aBrowser) { mBrowser = aBrowser; }
@@ -208,7 +206,6 @@ class WebBrowserChrome2Stub final : public nsIWebBrowserChrome,
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIWEBBROWSERCHROME NS_DECL_NSIWEBBROWSERCHROME
NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIEMBEDDINGSITEWINDOW
}; };
NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub) NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub)
@@ -216,7 +213,6 @@ NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(WebBrowserChrome2Stub) NS_IMPL_ADDREF(WebBrowserChrome2Stub)
@@ -258,59 +254,32 @@ WebBrowserChrome2Stub::GetInterface(const nsIID& aIID, void** aSink) {
return QueryInterface(aIID, aSink); return QueryInterface(aIID, aSink);
} }
// nsIEmbeddingSiteWindow impl
NS_IMETHODIMP NS_IMETHODIMP
WebBrowserChrome2Stub::GetDimensions(uint32_t flags, int32_t* x, int32_t* y, WebBrowserChrome2Stub::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* cx, int32_t* cy) { int32_t* aY, int32_t* aCX, int32_t* aCY) {
if (x) { if (aX) {
*x = 0; *aX = 0;
} }
if (aY) {
if (y) { *aY = 0;
*y = 0;
} }
if (aCX) {
if (cx) { *aCX = 0;
*cx = 0;
} }
if (aCY) {
if (cy) { *aCY = 0;
*cy = 0;
} }
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
WebBrowserChrome2Stub::SetDimensions(uint32_t flags, int32_t x, int32_t y, WebBrowserChrome2Stub::SetDimensions(DimensionRequest&& aRequest) {
int32_t cx, int32_t cy) { nsCOMPtr<nsIBaseWindow> window(do_QueryInterface(mBrowser));
nsCOMPtr<nsIBaseWindow> window = do_QueryInterface(mBrowser); NS_ENSURE_STATE(window);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); // Inner and outer dimensions are equal.
window->SetSize(cx, cy, true); aRequest.mDimensionKind = DimensionKind::Outer;
return NS_OK; MOZ_TRY(aRequest.SupplementFrom(window));
} return aRequest.ApplyOuterTo(window);
NS_IMETHODIMP
WebBrowserChrome2Stub::GetVisibility(bool* aVisibility) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserChrome2Stub::SetVisibility(bool aVisibility) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserChrome2Stub::GetTitle(nsAString& aTitle) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserChrome2Stub::SetTitle(const nsAString& aTitle) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserChrome2Stub::GetSiteWindow(void** aSiteWindow) {
return NS_ERROR_NOT_IMPLEMENTED;
} }
NS_IMETHODIMP NS_IMETHODIMP

View File

@@ -10,7 +10,6 @@
// Helper Classes // Helper Classes
#include "nsString.h" #include "nsString.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIDocShellTreeItem.h" #include "nsIDocShellTreeItem.h"
// Interfaces needed to include // Interfaces needed to include
@@ -77,10 +76,6 @@ NS_IMETHODIMP nsChromeTreeOwner::GetInterface(const nsIID& aIID, void** aSink) {
NS_ENSURE_STATE(mAppWindow); NS_ENSURE_STATE(mAppWindow);
return mAppWindow->GetInterface(aIID, aSink); return mAppWindow->GetInterface(aIID, aSink);
} }
if (aIID.Equals(NS_GET_IID(nsIEmbeddingSiteWindow))) {
NS_ENSURE_STATE(mAppWindow);
return mAppWindow->GetInterface(aIID, aSink);
}
if (aIID.Equals(NS_GET_IID(nsIAppWindow))) { if (aIID.Equals(NS_GET_IID(nsIAppWindow))) {
NS_ENSURE_STATE(mAppWindow); NS_ENSURE_STATE(mAppWindow);
return mAppWindow->QueryInterface(aIID, aSink); return mAppWindow->QueryInterface(aIID, aSink);
@@ -311,6 +306,27 @@ NS_IMETHODIMP nsChromeTreeOwner::GetPositionAndSize(int32_t* x, int32_t* y,
return mAppWindow->GetPositionAndSize(x, y, cx, cy); return mAppWindow->GetPositionAndSize(x, y, cx, cy);
} }
NS_IMETHODIMP
nsChromeTreeOwner::SetDimensions(DimensionRequest&& aRequest) {
MOZ_TRY(aRequest.SupplementFrom(this));
if (aRequest.mDimensionKind == DimensionKind::Outer) {
return aRequest.ApplyOuterTo(this);
}
return aRequest.ApplyInnerTo(this, /* aAsRootShell */ true);
}
NS_IMETHODIMP
nsChromeTreeOwner::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
if (aDimensionKind == DimensionKind::Outer) {
return GetPositionAndSize(aX, aY, aCX, aCY);
}
if (aY || aX) {
return NS_ERROR_NOT_IMPLEMENTED;
}
return GetRootShellSize(aCX, aCY);
}
NS_IMETHODIMP nsChromeTreeOwner::Repaint(bool aForce) { NS_IMETHODIMP nsChromeTreeOwner::Repaint(bool aForce) {
NS_ENSURE_STATE(mAppWindow); NS_ENSURE_STATE(mAppWindow);
return mAppWindow->Repaint(aForce); return mAppWindow->Repaint(aForce);

View File

@@ -13,7 +13,6 @@
#include "nsIDOMWindow.h" #include "nsIDOMWindow.h"
#include "nsIDOMChromeWindow.h" #include "nsIDOMChromeWindow.h"
#include "nsIBrowserDOMWindow.h" #include "nsIBrowserDOMWindow.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIOpenWindowInfo.h" #include "nsIOpenWindowInfo.h"
#include "nsIPrompt.h" #include "nsIPrompt.h"
#include "nsIAuthPrompt.h" #include "nsIAuthPrompt.h"
@@ -44,41 +43,12 @@
using namespace mozilla; using namespace mozilla;
//*****************************************************************************
//*** nsSiteWindow declaration
//*****************************************************************************
class nsSiteWindow : public nsIEmbeddingSiteWindow {
// nsSiteWindow shares a lifetime with nsContentTreeOwner, and proxies it's
// AddRef and Release calls to said object.
// When nsContentTreeOwner is destroyed, nsSiteWindow will be destroyed as
// well. nsContentTreeOwner is a friend class of nsSiteWindow such that it can
// call nsSiteWindow's destructor, which is private, as public destructors on
// reference counted classes are generally unsafe.
friend class nsContentTreeOwner;
public:
explicit nsSiteWindow(nsContentTreeOwner* aAggregator);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIEMBEDDINGSITEWINDOW
private:
virtual ~nsSiteWindow();
nsContentTreeOwner* mAggregator;
};
//***************************************************************************** //*****************************************************************************
//*** nsContentTreeOwner: Object Management //*** nsContentTreeOwner: Object Management
//***************************************************************************** //*****************************************************************************
nsContentTreeOwner::nsContentTreeOwner(bool fPrimary) nsContentTreeOwner::nsContentTreeOwner(bool fPrimary)
: mAppWindow(nullptr), mPrimary(fPrimary) { : mAppWindow(nullptr), mPrimary(fPrimary) {}
// note if this fails, QI on nsIEmbeddingSiteWindow(2) will simply fail
mSiteWindow = new nsSiteWindow(this);
}
nsContentTreeOwner::~nsContentTreeOwner() { delete mSiteWindow; }
//***************************************************************************** //*****************************************************************************
// nsContentTreeOwner::nsISupports // nsContentTreeOwner::nsISupports
@@ -94,15 +64,6 @@ NS_INTERFACE_MAP_BEGIN(nsContentTreeOwner)
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIWindowProvider) NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
// NOTE: This is using aggregation because there are some properties and
// method on nsIBaseWindow (which we implement) and on
// nsIEmbeddingSiteWindow (which we also implement) that have the same name.
// And it just so happens that we want different behavior for these methods
// and properties depending on the interface through which they're called
// (SetFocus() is a good example here). If it were not for that, we could
// ditch the aggregation and just deal with not being able to use NS_DECL_*
// macros for this stuff....
NS_INTERFACE_MAP_ENTRY_AGGREGATED(nsIEmbeddingSiteWindow, mSiteWindow)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
//***************************************************************************** //*****************************************************************************
@@ -112,7 +73,7 @@ NS_INTERFACE_MAP_END
NS_IMETHODIMP nsContentTreeOwner::GetInterface(const nsIID& aIID, NS_IMETHODIMP nsContentTreeOwner::GetInterface(const nsIID& aIID,
void** aSink) { void** aSink) {
NS_ENSURE_ARG_POINTER(aSink); NS_ENSURE_ARG_POINTER(aSink);
*aSink = 0; *aSink = nullptr;
if (aIID.Equals(NS_GET_IID(nsIPrompt))) { if (aIID.Equals(NS_GET_IID(nsIPrompt))) {
NS_ENSURE_STATE(mAppWindow); NS_ENSURE_STATE(mAppWindow);
@@ -447,6 +408,27 @@ NS_IMETHODIMP nsContentTreeOwner::GetPositionAndSize(int32_t* aX, int32_t* aY,
return mAppWindow->GetPositionAndSize(aX, aY, aCX, aCY); return mAppWindow->GetPositionAndSize(aX, aY, aCX, aCY);
} }
NS_IMETHODIMP
nsContentTreeOwner::SetDimensions(DimensionRequest&& aRequest) {
MOZ_TRY(aRequest.SupplementFrom(this));
if (aRequest.mDimensionKind == DimensionKind::Outer) {
return aRequest.ApplyOuterTo(this);
}
return aRequest.ApplyInnerTo(this, /* aAsRootShell */ false);
}
NS_IMETHODIMP
nsContentTreeOwner::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
int32_t* aY, int32_t* aCX, int32_t* aCY) {
if (aDimensionKind == DimensionKind::Outer) {
return GetPositionAndSize(aX, aY, aCX, aCY);
}
if (aY || aX) {
return NS_ERROR_NOT_IMPLEMENTED;
}
return GetPrimaryContentSize(aCX, aCY);
}
NS_IMETHODIMP nsContentTreeOwner::Repaint(bool aForce) { NS_IMETHODIMP nsContentTreeOwner::Repaint(bool aForce) {
NS_ENSURE_STATE(mAppWindow); NS_ENSURE_STATE(mAppWindow);
return mAppWindow->Repaint(aForce); return mAppWindow->Repaint(aForce);
@@ -611,56 +593,23 @@ void nsContentTreeOwner::AppWindow(mozilla::AppWindow* aAppWindow) {
mozilla::AppWindow* nsContentTreeOwner::AppWindow() { return mAppWindow; } mozilla::AppWindow* nsContentTreeOwner::AppWindow() { return mAppWindow; }
//*****************************************************************************
//*** nsSiteWindow implementation
//*****************************************************************************
nsSiteWindow::nsSiteWindow(nsContentTreeOwner* aAggregator) {
mAggregator = aAggregator;
}
nsSiteWindow::~nsSiteWindow() {}
NS_IMPL_ADDREF_USING_AGGREGATOR(nsSiteWindow, mAggregator)
NS_IMPL_RELEASE_USING_AGGREGATOR(nsSiteWindow, mAggregator)
NS_INTERFACE_MAP_BEGIN(nsSiteWindow)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
NS_INTERFACE_MAP_END_AGGREGATED(mAggregator)
NS_IMETHODIMP
nsSiteWindow::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY,
int32_t aCX, int32_t aCY) {
// XXX we're ignoring aFlags
return mAggregator->SetPositionAndSize(aX, aY, aCX, aCY,
nsIBaseWindow::eRepaint);
}
NS_IMETHODIMP
nsSiteWindow::GetDimensions(uint32_t aFlags, int32_t* aX, int32_t* aY,
int32_t* aCX, int32_t* aCY) {
// XXX we're ignoring aFlags
return mAggregator->GetPositionAndSize(aX, aY, aCX, aCY);
}
/* this implementation focuses another window. if there isn't another /* this implementation focuses another window. if there isn't another
window to focus, we do nothing. */ window to focus, we do nothing. */
NS_IMETHODIMP NS_IMETHODIMP
nsSiteWindow::Blur(void) { nsContentTreeOwner::Blur() {
NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID); NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID);
nsCOMPtr<nsISimpleEnumerator> windowEnumerator; nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
nsCOMPtr<nsIAppWindow> appWindow; nsCOMPtr<nsIAppWindow> appWindow;
bool more, foundUs; bool more, foundUs;
AppWindow* ourWindow = mAggregator->AppWindow();
{ {
nsCOMPtr<nsIWindowMediator> windowMediator( nsCOMPtr<nsIWindowMediator> windowMediator(
do_GetService(kWindowMediatorCID)); do_GetService(kWindowMediatorCID));
if (windowMediator) if (windowMediator) {
windowMediator->GetZOrderAppWindowEnumerator( windowMediator->GetZOrderAppWindowEnumerator(
0, true, getter_AddRefs(windowEnumerator)); nullptr, true, getter_AddRefs(windowEnumerator));
}
} }
if (!windowEnumerator) return NS_ERROR_FAILURE; if (!windowEnumerator) return NS_ERROR_FAILURE;
@@ -685,7 +634,9 @@ nsSiteWindow::Blur(void) {
if (!appWindow) appWindow = nextAppWindow; if (!appWindow) appWindow = nextAppWindow;
// look for us // look for us
if (nextAppWindow == ourWindow) foundUs = true; if (nextAppWindow == mAppWindow) {
foundUs = true;
}
windowEnumerator->HasMoreElements(&more); windowEnumerator->HasMoreElements(&more);
} }
@@ -703,28 +654,3 @@ nsSiteWindow::Blur(void) {
} }
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsSiteWindow::GetVisibility(bool* aVisibility) {
return mAggregator->GetVisibility(aVisibility);
}
NS_IMETHODIMP
nsSiteWindow::SetVisibility(bool aVisibility) {
return mAggregator->SetVisibility(aVisibility);
}
NS_IMETHODIMP
nsSiteWindow::GetTitle(nsAString& aTitle) {
return mAggregator->GetTitle(aTitle);
}
NS_IMETHODIMP
nsSiteWindow::SetTitle(const nsAString& aTitle) {
return mAggregator->SetTitle(aTitle);
}
NS_IMETHODIMP
nsSiteWindow::GetSiteWindow(void** aSiteWindow) {
return mAggregator->GetParentNativeWindow(aSiteWindow);
}

View File

@@ -22,7 +22,6 @@
namespace mozilla { namespace mozilla {
class AppWindow; class AppWindow;
} }
class nsSiteWindow;
class nsContentTreeOwner final : public nsIDocShellTreeOwner, class nsContentTreeOwner final : public nsIDocShellTreeOwner,
public nsIBaseWindow, public nsIBaseWindow,
@@ -30,7 +29,6 @@ class nsContentTreeOwner final : public nsIDocShellTreeOwner,
public nsIWebBrowserChrome, public nsIWebBrowserChrome,
public nsIWindowProvider { public nsIWindowProvider {
friend class mozilla::AppWindow; friend class mozilla::AppWindow;
friend class nsSiteWindow;
public: public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@@ -38,19 +36,25 @@ class nsContentTreeOwner final : public nsIDocShellTreeOwner,
NS_DECL_NSIBASEWINDOW NS_DECL_NSIBASEWINDOW
NS_DECL_NSIDOCSHELLTREEOWNER NS_DECL_NSIDOCSHELLTREEOWNER
NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIWEBBROWSERCHROME
NS_DECL_NSIWINDOWPROVIDER NS_DECL_NSIWINDOWPROVIDER
/* nsIWebBrowserChrome (Get/SetDimensions overlap with nsIBaseWindow) */
NS_IMETHOD SetLinkStatus(const nsAString& status) override;
NS_IMETHOD GetChromeFlags(uint32_t* aChromeFlags) override;
NS_IMETHOD SetChromeFlags(uint32_t aChromeFlags) override;
NS_IMETHOD ShowAsModal() override;
NS_IMETHOD IsWindowModal(bool* _retval) override;
NS_IMETHOD Blur() override;
protected: protected:
explicit nsContentTreeOwner(bool fPrimary); explicit nsContentTreeOwner(bool fPrimary);
virtual ~nsContentTreeOwner(); virtual ~nsContentTreeOwner() = default;
void AppWindow(mozilla::AppWindow* aAppWindow); void AppWindow(mozilla::AppWindow* aAppWindow);
mozilla::AppWindow* AppWindow(); mozilla::AppWindow* AppWindow();
protected: protected:
mozilla::AppWindow* mAppWindow; mozilla::AppWindow* mAppWindow;
nsSiteWindow* mSiteWindow;
bool mPrimary; bool mPrimary;
}; };