From 3ebfe519524866af4e8ee1e37d4f9d2b96cd598e Mon Sep 17 00:00:00 2001 From: Kathy Brade Date: Wed, 13 Apr 2016 10:50:38 -0400 Subject: [PATCH] Bug 6786: Do not expose system colors to CSS or canvas. Restore the portion of this fix that was not upstreamed as part of https://bugzilla.mozilla.org/show_bug.cgi?id=232227: use properly contrasting colors if the desktop theme specifies white on black for text colors (see bug 7920). These color choices are not exposed to content. --- layout/base/nsLayoutUtils.cpp | 50 +++++++++++++++++++++++++++++++++++ layout/base/nsLayoutUtils.h | 4 +++ layout/generic/nsFrame.cpp | 6 ++++- widget/LookAndFeel.h | 3 +++ widget/nsXPLookAndFeel.cpp | 41 ++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+), 1 deletion(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index ed34f39cefdd8..cc67f5156a245 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -5559,13 +5559,63 @@ ShouldDarkenColors(nsPresContext* aPresContext) nscolor nsLayoutUtils::GetColor(nsIFrame* aFrame, nsCSSPropertyID aProperty) { + if (aProperty == eCSSProperty_color) + { + nscolor nativeColor = NS_RGB(0, 0, 0); + if (GetNativeTextColor(aFrame, nativeColor)) + return nativeColor; + } + nscolor color = aFrame->GetVisitedDependentColor(aProperty); if (ShouldDarkenColors(aFrame->PresContext())) { color = DarkenColor(color); } + return color; } +bool +nsLayoutUtils::GetNativeTextColor(nsIFrame* aFrame, nscolor& aColor) +{ + nsPresContext *presContext = aFrame->PresContext(); + if (!presContext->IsChrome()) { + // If native appearance was used to draw the background of the containing + // frame, return a contrasting native foreground color instead of the + // color from the element's style. This avoids a problem where black + // text was displayed on a black background when a Windows theme such as + // "High Contrast Black" was used. The background is drawn inside + // nsNativeThemeWin::ClassicDrawWidgetBackground(). + // + // Because both the background color and this foreground color are used + // directly without exposing the colors via CSS computed styles, the + // native colors are not leaked to content. + nsIFrame* bgFrame = + nsCSSRendering::FindNonTransparentBackgroundFrame(aFrame); + if (bgFrame) { + const nsStyleDisplay* displayData = bgFrame->StyleDisplay(); + uint8_t widgetType = displayData->mAppearance; + nsITheme *theme = presContext->GetTheme(); + if (theme && widgetType && theme->ThemeSupportsWidget(presContext, + bgFrame, + widgetType)) { + bool isDisabled = false; + nsIContent* frameContent = bgFrame->GetContent(); + if (frameContent && frameContent->IsElement()) { + EventStates es = frameContent->AsElement()->State(); + isDisabled = es.HasState(NS_EVENT_STATE_DISABLED); + } + + if (NS_SUCCEEDED(LookAndFeel::GetColorForNativeAppearance(widgetType, + isDisabled, &aColor))) { + return true; + } + } + } + } + + return false; +} + gfxFloat nsLayoutUtils::GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext, nscoord aY, nscoord aAscent) diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index d9580a3dfb5d9..bb0724b556c3a 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1544,6 +1544,10 @@ public: // Get a suitable foreground color for painting aProperty for aFrame. static nscolor GetColor(nsIFrame* aFrame, nsCSSPropertyID aProperty); + // Get the native text color if appropriate. If false is returned, callers + // should fallback to the CSS color. + static bool GetNativeTextColor(nsIFrame* aFrame, nscolor& aColor); + // Get a baseline y position in app units that is snapped to device pixels. static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext, nscoord aY, nscoord aAscent); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 69791d5c52ab4..96fa480a707d2 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1834,7 +1834,11 @@ nsIFrame::DisplayCaret(nsDisplayListBuilder* aBuilder, nscolor nsIFrame::GetCaretColorAt(int32_t aOffset) { - // Use text color. + nscolor color = NS_RGB(0, 0, 0); + if (nsLayoutUtils::GetNativeTextColor(this, color)) + return color; + + // Use CSS text color. return StyleColor()->mColor; } diff --git a/widget/LookAndFeel.h b/widget/LookAndFeel.h index 3a4929c9f3a6a..ac7349c225343 100644 --- a/widget/LookAndFeel.h +++ b/widget/LookAndFeel.h @@ -517,6 +517,9 @@ public: static nsresult GetColor(ColorID aID, bool aUseStandinsForNativeColors, nscolor* aResult); + static nsresult GetColorForNativeAppearance(uint8_t aWidgetType, + bool aIsDisabled, nscolor* aResult); + /** * GetInt() and GetFloat() return a int or float value for aID. The result * might be distance, time, some flags or a int value which has particular diff --git a/widget/nsXPLookAndFeel.cpp b/widget/nsXPLookAndFeel.cpp index 54c61982943fb..140af4868e575 100644 --- a/widget/nsXPLookAndFeel.cpp +++ b/widget/nsXPLookAndFeel.cpp @@ -11,6 +11,7 @@ #include "nsLookAndFeel.h" #include "nsCRT.h" #include "nsFont.h" +#include "nsThemeConstants.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/Preferences.h" #include "mozilla/gfx/2D.h" @@ -914,6 +915,46 @@ LookAndFeel::GetColor(ColorID aID, bool aUseStandinsForNativeColors, aUseStandinsForNativeColors, *aResult); } +// static +nsresult +LookAndFeel::GetColorForNativeAppearance(uint8_t aWidgetType, bool aIsDisabled, + nscolor* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + + ColorID colorID = eColorID_LAST_COLOR; + switch (aWidgetType) { + case NS_THEME_TEXTFIELD: + case NS_THEME_TEXTFIELD_MULTILINE: + case NS_THEME_LISTBOX: + case NS_THEME_MENULIST: + case NS_THEME_MENULIST_TEXTFIELD: + case NS_THEME_TREEVIEW: + colorID = (aIsDisabled) ? eColorID_graytext : eColorID__moz_fieldtext; + break; + + case NS_THEME_TOOLTIP: + colorID = eColorID_infotext; + break; + + case NS_THEME_BUTTON: + case NS_THEME_GROUPBOX: + case NS_THEME_PROGRESSBAR: + case NS_THEME_PROGRESSBAR_VERTICAL: + case NS_THEME_TABPANEL: + case NS_THEME_STATUSBAR: + case NS_THEME_RESIZERPANEL: + colorID = (aIsDisabled) ? eColorID_graytext : eColorID_buttontext; + break; + } + + if (LookAndFeel::eColorID_LAST_COLOR == colorID) + return NS_ERROR_FAILURE; + + *aResult = NS_RGB(0, 0, 0); + return nsLookAndFeel::GetInstance()->NativeGetColor(colorID, *aResult); +} + // static nsresult LookAndFeel::GetInt(IntID aID, int32_t* aResult) -- GitLab