DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (d38398e5144e)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

/*
 * style sheet and style rule processor representing style attributes
 */

#include "nsHTMLCSSStyleSheet.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/css/StyleRule.h"
#include "mozilla/DeclarationBlockInlines.h"
#include "nsIStyleRuleProcessor.h"
#include "nsPresContext.h"
#include "nsRuleWalker.h"
#include "nsRuleProcessorData.h"
#include "mozilla/dom/Element.h"
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
#include "nsCSSPseudoElements.h"
#include "mozilla/RestyleManager.h"
#include "mozilla/RestyleManagerInlines.h"

using namespace mozilla;
using namespace mozilla::dom;

nsHTMLCSSStyleSheet::nsHTMLCSSStyleSheet()
{
}

nsHTMLCSSStyleSheet::~nsHTMLCSSStyleSheet()
{
  // We may go away before all of our cached style attributes do,
  // so clean up any that are left.
  for (auto iter = mCachedStyleAttrs.Iter(); !iter.Done(); iter.Next()) {
    MiscContainer*& value = iter.Data();

    // Ideally we'd just call MiscContainer::Evict, but we can't do that since
    // we're iterating the hashtable.
    if (value->mType == nsAttrValue::eCSSDeclaration) {
      DeclarationBlock* declaration = value->mValue.mCSSDeclaration;
      declaration->SetHTMLCSSStyleSheet(nullptr);
    } else {
      MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
    }

    value->mValue.mCached = 0;
    iter.Remove();
  }
}

NS_IMPL_ISUPPORTS(nsHTMLCSSStyleSheet, nsIStyleRuleProcessor)

/* virtual */ void
nsHTMLCSSStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
{
  ElementRulesMatching(aData->mPresContext, aData->mElement,
                       aData->mRuleWalker);
}

void
nsHTMLCSSStyleSheet::ElementRulesMatching(nsPresContext* aPresContext,
                                          Element* aElement,
                                          nsRuleWalker* aRuleWalker)
{
  // just get the one and only style rule from the content's STYLE attribute
  DeclarationBlock* declaration = aElement->GetInlineStyleDeclaration();
  if (declaration) {
    declaration->SetImmutable();
    aRuleWalker->Forward(declaration->AsGecko());
  }

  declaration = aElement->GetSMILOverrideStyleDeclaration();
  if (declaration) {
    MOZ_ASSERT(aPresContext->RestyleManager()->IsGecko(),
               "stylo: ElementRulesMatching must not be called when we have "
               "a Servo-backed style system");
    GeckoRestyleManager* restyleManager =
      aPresContext->RestyleManager()->AsGecko();
    if (!restyleManager->SkipAnimationRules()) {
      // Animation restyle (or non-restyle traversal of rules)
      // Now we can walk SMIL overrride style, without triggering transitions.
      declaration->SetImmutable();
      aRuleWalker->Forward(declaration->AsGecko());
    }
  }
}

void
nsHTMLCSSStyleSheet::PseudoElementRulesMatching(Element* aPseudoElement,
                                                CSSPseudoElementType
                                                  aPseudoType,
                                                nsRuleWalker* aRuleWalker)
{
  MOZ_ASSERT(nsCSSPseudoElements::
               PseudoElementSupportsStyleAttribute(aPseudoType));
  MOZ_ASSERT(aPseudoElement);

  // just get the one and only style rule from the content's STYLE attribute
  DeclarationBlock* declaration = aPseudoElement->GetInlineStyleDeclaration();
  if (declaration) {
    declaration->SetImmutable();
    aRuleWalker->Forward(declaration->AsGecko());
  }
}

/* virtual */ void
nsHTMLCSSStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData)
{
  if (nsCSSPseudoElements::PseudoElementSupportsStyleAttribute(aData->mPseudoType) &&
      aData->mPseudoElement) {
    PseudoElementRulesMatching(aData->mPseudoElement, aData->mPseudoType,
                               aData->mRuleWalker);
  }
}

/* virtual */ void
nsHTMLCSSStyleSheet::RulesMatching(AnonBoxRuleProcessorData* aData)
{
}

#ifdef MOZ_XUL
/* virtual */ void
nsHTMLCSSStyleSheet::RulesMatching(XULTreeRuleProcessorData* aData)
{
}
#endif

// Test if style is dependent on content state
/* virtual */ nsRestyleHint
nsHTMLCSSStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData)
{
  return nsRestyleHint(0);
}

/* virtual */ nsRestyleHint
nsHTMLCSSStyleSheet::HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData)
{
  return nsRestyleHint(0);
}

/* virtual */ bool
nsHTMLCSSStyleSheet::HasDocumentStateDependentStyle(StateRuleProcessorData* aData)
{
  return false;
}

// Test if style is dependent on attribute
/* virtual */ nsRestyleHint
nsHTMLCSSStyleSheet::HasAttributeDependentStyle(
    AttributeRuleProcessorData* aData,
    RestyleHintData& aRestyleHintDataResult)
{
  // Perhaps should check that it's XUL, SVG, (or HTML) namespace, but
  // it doesn't really matter.
  if (aData->mAttrHasChanged && aData->mAttribute == nsGkAtoms::style) {
    return eRestyle_StyleAttribute;
  }

  return nsRestyleHint(0);
}

/* virtual */ bool
nsHTMLCSSStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext)
{
  return false;
}

/* virtual */ size_t
nsHTMLCSSStyleSheet::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
  // The size of mCachedStyleAttrs's mTable member (a PLDHashTable) is
  // significant in itself, but more significant is the size of the nsString
  // members of the nsStringHashKeys.
  size_t n = 0;
  n += mCachedStyleAttrs.ShallowSizeOfExcludingThis(aMallocSizeOf);
  for (auto iter = mCachedStyleAttrs.ConstIter(); !iter.Done(); iter.Next()) {
    // We don't own the MiscContainers (the hash table values) so we don't
    // count them. We do care about the size of the nsString members in the
    // keys though.
    n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
  }
  return n;
}

/* virtual */ size_t
nsHTMLCSSStyleSheet::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
  return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}

void
nsHTMLCSSStyleSheet::CacheStyleAttr(const nsAString& aSerialized,
                                    MiscContainer* aValue)
{
  mCachedStyleAttrs.Put(aSerialized, aValue);
}

void
nsHTMLCSSStyleSheet::EvictStyleAttr(const nsAString& aSerialized,
                                    MiscContainer* aValue)
{
#ifdef DEBUG
  {
    NS_ASSERTION(aValue == mCachedStyleAttrs.Get(aSerialized),
                 "Cached value does not match?!");
  }
#endif
  mCachedStyleAttrs.Remove(aSerialized);
}

MiscContainer*
nsHTMLCSSStyleSheet::LookupStyleAttr(const nsAString& aSerialized)
{
  return mCachedStyleAttrs.Get(aSerialized);
}