Commit de975c21 authored by Kathleen Brade's avatar Kathleen Brade Committed by Georg Koppen
Browse files

Bug #6786: Do not expose system colors to CSS or canvas.

This patch also contains a hack to use properly contrasting colors if the
desktop theme specifies white on black for text colors (see
https://trac.torproject.org/projects/tor/ticket/7920). These color choices are
also not exposed to content.
parent 46305cbb
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -62,8 +62,9 @@ public:
  }

protected:
  CanvasGradient(CanvasRenderingContext2D* aContext, Type aType)
  CanvasGradient(CanvasRenderingContext2D* aContext, mozilla::css::Loader *aLoader, Type aType)
    : mContext(aContext)
    , mCSSLoader(aLoader)
    , mType(aType)
  {
  }
@@ -71,6 +72,7 @@ protected:
  nsRefPtr<CanvasRenderingContext2D> mContext;
  nsTArray<mozilla::gfx::GradientStop> mRawStops;
  mozilla::RefPtr<mozilla::gfx::GradientStops> mStops;
  mozilla::css::Loader* mCSSLoader; // not ref counted, it owns us
  Type mType;
  virtual ~CanvasGradient() {}
};
+21 −5
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "nsCSSParser.h"
#include "mozilla/css/StyleRule.h"
#include "mozilla/css/Declaration.h"
#include "mozilla/css/Loader.h"
#include "nsComputedDOMStyle.h"
#include "nsStyleSet.h"

@@ -181,9 +182,10 @@ class CanvasRadialGradient : public CanvasGradient
{
public:
  CanvasRadialGradient(CanvasRenderingContext2D* aContext,
                       mozilla::css::Loader *aLoader,
                       const Point &aBeginOrigin, Float aBeginRadius,
                       const Point &aEndOrigin, Float aEndRadius)
    : CanvasGradient(aContext, Type::RADIAL)
    : CanvasGradient(aContext, aLoader, Type::RADIAL)
    , mCenter1(aBeginOrigin)
    , mCenter2(aEndOrigin)
    , mRadius1(aBeginRadius)
@@ -201,8 +203,9 @@ class CanvasLinearGradient : public CanvasGradient
{
public:
  CanvasLinearGradient(CanvasRenderingContext2D* aContext,
                       mozilla::css::Loader *aLoader,
                       const Point &aBegin, const Point &aEnd)
    : CanvasGradient(aContext, Type::LINEAR)
    : CanvasGradient(aContext, aLoader, Type::LINEAR)
    , mBegin(aBegin)
    , mEnd(aEnd)
  {
@@ -667,8 +670,16 @@ CanvasGradient::AddColorStop(float offset, const nsAString& colorstr, ErrorResul
    return;
  }

  nsIPresShell* presShell = nullptr;
  if (mCSSLoader) {
    nsIDocument *doc = mCSSLoader->GetDocument();
    if (doc)
      presShell = doc->GetShell();
  }

  nscolor color;
  if (!nsRuleNode::ComputeColor(value, nullptr, nullptr, color)) {
  if (!nsRuleNode::ComputeColor(value, presShell ? presShell->GetPresContext() : nullptr,
                                nullptr, color)) {
    rv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
    return;
  }
@@ -1917,8 +1928,11 @@ CanvasRenderingContext2D::GetFillRule(nsAString& aString)
already_AddRefed<CanvasGradient>
CanvasRenderingContext2D::CreateLinearGradient(double x0, double y0, double x1, double y1)
{
  nsIDocument *doc = mCanvasElement ? mCanvasElement->OwnerDoc() : nullptr;
  mozilla::css::Loader *cssLoader = doc ? doc->CSSLoader() : nullptr;

  nsRefPtr<CanvasGradient> grad =
    new CanvasLinearGradient(this, Point(x0, y0), Point(x1, y1));
    new CanvasLinearGradient(this, cssLoader, Point(x0, y0), Point(x1, y1));

  return grad.forget();
}
@@ -1933,8 +1947,10 @@ CanvasRenderingContext2D::CreateRadialGradient(double x0, double y0, double r0,
    return nullptr;
  }

  nsIDocument *doc = mCanvasElement ? mCanvasElement->OwnerDoc() : nullptr;
  mozilla::css::Loader *cssLoader = doc ? doc->CSSLoader() : nullptr;
  nsRefPtr<CanvasGradient> grad =
    new CanvasRadialGradient(this, Point(x0, y0), r0, Point(x1, y1), r1);
    new CanvasRadialGradient(this, cssLoader, Point(x0, y0), r0, Point(x1, y1), r1);

  return grad.forget();
}
+50 −0
Original line number Diff line number Diff line
@@ -5097,13 +5097,63 @@ ShouldDarkenColors(nsPresContext* aPresContext)
nscolor
nsLayoutUtils::GetColor(nsIFrame* aFrame, nsCSSProperty 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)
+4 −0
Original line number Diff line number Diff line
@@ -1474,6 +1474,10 @@ public:
  // Get a suitable foreground color for painting aProperty for aFrame.
  static nscolor GetColor(nsIFrame* aFrame, nsCSSProperty 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);
+5 −1
Original line number Diff line number Diff line
@@ -1575,7 +1575,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;
}

Loading