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

Macros

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
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */

/* atom list for CSS pseudo-classes */

#include "mozilla/ArrayUtils.h"

#include "nsCSSPseudoClasses.h"
#include "nsCSSPseudoElements.h"
#include "nsStaticAtom.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/Element.h"
#include "nsString.h"
#include "nsAttrValueInlines.h"
#include "nsIMozBrowserFrame.h"

using namespace mozilla;

// define storage for all atoms
#define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) \
  static nsIAtom* sPseudoClass_##_name;
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS

#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
  NS_STATIC_ATOM_BUFFER(name_##_pseudo_class_buffer, value_)
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS

#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
  static_assert(!((flags_) & CSS_PSEUDO_CLASS_ENABLED_IN_CHROME) || \
                ((flags_) & CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), \
                "Pseudo-class '" #name_ "' is enabled in chrome, so it " \
                "should also be enabled in UA sheets");
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS

// Array of nsStaticAtom for each of the pseudo-classes.
static const nsStaticAtom CSSPseudoClasses_info[] = {
#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
  NS_STATIC_ATOM(name_##_pseudo_class_buffer, &sPseudoClass_##name_),
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS
};

// Flags data for each of the pseudo-classes, which must be separate
// from the previous array since there's no place for it in
// nsStaticAtom.
/* static */ const uint32_t
nsCSSPseudoClasses::kPseudoClassFlags[] = {
#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
  flags_,
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS
};

/* static */ bool
nsCSSPseudoClasses::sPseudoClassEnabled[] = {
// If the pseudo class has any "ENABLED_IN" flag set, it is disabled by
// default. Note that, if a pseudo class has pref, whatever its default
// value is, it'll later be changed in nsCSSPseudoClasses::AddRefAtoms()
// If the pseudo class has "ENABLED_IN" flags but doesn't have a pref,
// it is an internal pseudo class which is disabled elsewhere.
#define IS_ENABLED_BY_DEFAULT(flags_) \
  (!((flags_) & CSS_PSEUDO_CLASS_ENABLED_MASK))
#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
  IS_ENABLED_BY_DEFAULT(flags_),
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS
#undef IS_ENABLED_BY_DEFAULT
};

void nsCSSPseudoClasses::AddRefAtoms()
{
  NS_RegisterStaticAtoms(CSSPseudoClasses_info);

#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_)                        \
  if (pref_[0]) {                                                             \
    auto idx = static_cast<CSSPseudoElementTypeBase>(Type::name_);            \
    Preferences::AddBoolVarCache(&sPseudoClassEnabled[idx], pref_);           \
  }
#include "nsCSSPseudoClassList.h"
#undef CSS_PSEUDO_CLASS
}

bool
nsCSSPseudoClasses::HasStringArg(Type aType)
{
  return aType == Type::lang ||
         aType == Type::mozEmptyExceptChildrenWithLocalname ||
         aType == Type::mozSystemMetric ||
         aType == Type::mozLocaleDir ||
         aType == Type::dir;
}

bool
nsCSSPseudoClasses::HasNthPairArg(Type aType)
{
  return aType == Type::nthChild ||
         aType == Type::nthLastChild ||
         aType == Type::nthOfType ||
         aType == Type::nthLastOfType;
}

void
nsCSSPseudoClasses::PseudoTypeToString(Type aType, nsAString& aString)
{
  MOZ_ASSERT(aType < Type::Count, "Unexpected type");
  auto idx = static_cast<CSSPseudoClassTypeBase>(aType);
  (*CSSPseudoClasses_info[idx].mAtom)->ToString(aString);
}

/* static */ CSSPseudoClassType
nsCSSPseudoClasses::GetPseudoType(nsIAtom* aAtom, EnabledState aEnabledState)
{
  for (uint32_t i = 0; i < ArrayLength(CSSPseudoClasses_info); ++i) {
    if (*CSSPseudoClasses_info[i].mAtom == aAtom) {
      Type type = Type(i);
      return IsEnabled(type, aEnabledState) ? type : Type::NotPseudo;
    }
  }
  return Type::NotPseudo;
}

/* static */ bool
nsCSSPseudoClasses::IsUserActionPseudoClass(Type aType)
{
  // See http://dev.w3.org/csswg/selectors4/#useraction-pseudos
  return aType == Type::hover ||
         aType == Type::active ||
         aType == Type::focus;
}

/* static */ Maybe<bool>
nsCSSPseudoClasses::MatchesElement(Type aType, const dom::Element* aElement)
{
  switch (aType) {
    case CSSPseudoClassType::mozNativeAnonymous:
      return Some(aElement->IsInNativeAnonymousSubtree());
    case CSSPseudoClassType::mozTableBorderNonzero: {
      if (!aElement->IsHTMLElement(nsGkAtoms::table)) {
        return Some(false);
      }
      const nsAttrValue *val = aElement->GetParsedAttr(nsGkAtoms::border);
      return Some(val && (val->Type() != nsAttrValue::eInteger ||
                          val->GetIntegerValue() != 0));
    }
    case CSSPseudoClassType::mozBrowserFrame: {
      nsIMozBrowserFrame* browserFrame =
        const_cast<Element*>(aElement)->GetAsMozBrowserFrame();
      return Some(browserFrame && browserFrame->GetReallyIsBrowser());
    }
    default:
      return Nothing();
  }
}