Bug 1744749 - Add an API to get the real canvas background color. r=jwatt

Extensions are using getComputedStyle(body).backgroundColor, which is
wrong at multiple levels.

The one that matters for this bug is that it is not color-scheme aware.

Depends on D133770

Differential Revision: https://phabricator.services.mozilla.com/D133771
This commit is contained in:
Emilio Cobos Álvarez 2021-12-16 14:56:32 +00:00
Родитель 67c757f108
Коммит a6fb6742a0
4 изменённых файлов: 66 добавлений и 39 удалений

Просмотреть файл

@ -2115,6 +2115,19 @@ nsDOMWindowUtils::GetNodeObservedByIMEContentObserver(nsINode** aNode) {
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetCanvasBackgroundColor(nsAString& aColor) {
if (RefPtr<Document> doc = GetDocument()) {
doc->FlushPendingNotifications(FlushType::Frames);
}
nscolor color = NS_RGB(255, 255, 255);
if (PresShell* presShell = GetPresShell()) {
color = presShell->ComputeCanvasBackground().mColor;
}
nsStyleUtil::GetSerializedColorValue(color, aColor);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetFocusedInputType(nsAString& aType) {
nsCOMPtr<nsIWidget> widget = GetWidget();

Просмотреть файл

@ -1687,6 +1687,11 @@ interface nsIDOMWindowUtils : nsISupports {
in AString aProperty,
in long aFlushType);
/**
* Returns the effective canvas background color for the window.
*/
readonly attribute AString canvasBackgroundColor;
/**
* Get the type of the currently focused html input, if any.
*/

Просмотреть файл

@ -5325,7 +5325,7 @@ static bool IsTransparentContainerElement(nsPresContext* aPresContext) {
return false;
}
nscolor PresShell::GetDefaultBackgroundColorToDraw() {
nscolor PresShell::GetDefaultBackgroundColorToDraw() const {
if (!mPresContext || !mPresContext->GetBackgroundColorDraw()) {
return NS_RGB(255, 255, 255);
}
@ -5356,47 +5356,51 @@ nscolor PresShell::GetDefaultBackgroundColorToDraw() {
}
void PresShell::UpdateCanvasBackground() {
auto canvasBg = ComputeCanvasBackground();
mCanvasBackgroundColor = canvasBg.mColor;
mHasCSSBackgroundColor = canvasBg.mCSSSpecified;
}
PresShell::CanvasBackground PresShell::ComputeCanvasBackground() const {
// If we have a frame tree and it has style information that
// specifies the background color of the canvas, update our local
// cache of that color.
nsIFrame* rootStyleFrame = FrameConstructor()->GetRootElementStyleFrame();
if (rootStyleFrame) {
ComputedStyle* bgStyle =
nsCSSRendering::FindRootFrameBackground(rootStyleFrame);
// XXX We should really be passing the canvasframe, not the root element
// style frame but we don't have access to the canvasframe here. It isn't
// a problem because only a few frames can return something other than true
// and none of them would be a canvas frame or root element style frame.
bool drawBackgroundImage = false;
bool drawBackgroundColor = false;
const nsStyleDisplay* disp = rootStyleFrame->StyleDisplay();
StyleAppearance appearance = disp->EffectiveAppearance();
if (rootStyleFrame->IsThemed(disp) &&
appearance != StyleAppearance::MozWinGlass &&
appearance != StyleAppearance::MozWinBorderlessGlass) {
// Ignore the CSS background-color if -moz-appearance is used and it is
// not one of the glass values. (Windows 7 Glass has traditionally not
// overridden background colors, so we preserve that behavior for now.)
mCanvasBackgroundColor = NS_RGBA(0, 0, 0, 0);
} else {
mCanvasBackgroundColor = nsCSSRendering::DetermineBackgroundColor(
mPresContext, bgStyle, rootStyleFrame, drawBackgroundImage,
drawBackgroundColor);
}
mHasCSSBackgroundColor = drawBackgroundColor;
if (mPresContext->IsRootContentDocumentCrossProcess() &&
!IsTransparentContainerElement(mPresContext)) {
mCanvasBackgroundColor = NS_ComposeColors(
GetDefaultBackgroundColorToDraw(), mCanvasBackgroundColor);
}
if (!rootStyleFrame) {
// If the root element of the document (ie html) has style 'display: none'
// then the document's background color does not get drawn; return the color
// we actually draw.
return {GetDefaultBackgroundColorToDraw(), false};
}
// If the root element of the document (ie html) has style 'display: none'
// then the document's background color does not get drawn; cache the
// color we actually draw.
if (!FrameConstructor()->GetRootElementFrame()) {
mCanvasBackgroundColor = GetDefaultBackgroundColorToDraw();
ComputedStyle* bgStyle =
nsCSSRendering::FindRootFrameBackground(rootStyleFrame);
// XXX We should really be passing the canvasframe, not the root element
// style frame but we don't have access to the canvasframe here. It isn't
// a problem because only a few frames can return something other than true
// and none of them would be a canvas frame or root element style frame.
nscolor color = NS_RGBA(0, 0, 0, 0);
bool drawBackgroundImage = false;
bool drawBackgroundColor = false;
const nsStyleDisplay* disp = rootStyleFrame->StyleDisplay();
StyleAppearance appearance = disp->EffectiveAppearance();
if (rootStyleFrame->IsThemed(disp) &&
appearance != StyleAppearance::MozWinGlass &&
appearance != StyleAppearance::MozWinBorderlessGlass) {
// Ignore the CSS background-color if -moz-appearance is used and it is
// not one of the glass values. (Windows 7 Glass has traditionally not
// overridden background colors, so we preserve that behavior for now.)
} else {
color = nsCSSRendering::DetermineBackgroundColor(
mPresContext, bgStyle, rootStyleFrame, drawBackgroundImage,
drawBackgroundColor);
}
if (mPresContext->IsRootContentDocumentCrossProcess() &&
!IsTransparentContainerElement(mPresContext)) {
color = NS_ComposeColors(
GetDefaultBackgroundColorToDraw(), color);
}
return {color, drawBackgroundColor};
}
nscolor PresShell::ComputeBackstopColor(nsView* aDisplayRoot) {

Просмотреть файл

@ -877,12 +877,17 @@ class PresShell final : public nsStubDocumentObserver,
* bug 488242, bug 476557 and other bugs mentioned there.
*/
void SetCanvasBackground(nscolor aColor) { mCanvasBackgroundColor = aColor; }
nscolor GetCanvasBackground() { return mCanvasBackgroundColor; }
nscolor GetCanvasBackground() const { return mCanvasBackgroundColor; }
/**
* Use the current frame tree (if it exists) to update the background
* color of the most recently drawn canvas.
* Use the current frame tree (if it exists) to update the background color of
* the most recently drawn canvas.
*/
struct CanvasBackground {
nscolor mColor = 0;
bool mCSSSpecified = false;
};
CanvasBackground ComputeCanvasBackground() const;
void UpdateCanvasBackground();
/**
@ -2760,7 +2765,7 @@ class PresShell final : public nsStubDocumentObserver,
PresShell* GetRootPresShell() const;
nscolor GetDefaultBackgroundColorToDraw();
nscolor GetDefaultBackgroundColorToDraw() const;
//////////////////////////////////////////////////////////////////////////////
// Approximate frame visibility tracking implementation.