Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/svg/SVGTests.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/dom/SVGTests.h"
8
#include "DOMSVGStringList.h"
9
#include "nsSVGFeatures.h"
10
#include "mozilla/dom/SVGSwitchElement.h"
11
#include "nsCharSeparatedTokenizer.h"
12
#include "nsStyleUtil.h"
13
#include "mozilla/Preferences.h"
14
15
namespace mozilla {
16
namespace dom {
17
18
nsStaticAtom** SVGTests::sStringListNames[3] =
19
{
20
  &nsGkAtoms::requiredFeatures,
21
  &nsGkAtoms::requiredExtensions,
22
  &nsGkAtoms::systemLanguage,
23
};
24
25
SVGTests::SVGTests()
26
0
{
27
0
  mStringListAttributes[LANGUAGE].SetIsCommaSeparated(true);
28
0
}
29
30
already_AddRefed<DOMSVGStringList>
31
SVGTests::RequiredFeatures()
32
0
{
33
0
  return DOMSVGStringList::GetDOMWrapper(
34
0
           &mStringListAttributes[FEATURES], AsSVGElement(), true, FEATURES);
35
0
}
36
37
already_AddRefed<DOMSVGStringList>
38
SVGTests::RequiredExtensions()
39
0
{
40
0
  return DOMSVGStringList::GetDOMWrapper(
41
0
           &mStringListAttributes[EXTENSIONS], AsSVGElement(), true, EXTENSIONS);
42
0
}
43
44
already_AddRefed<DOMSVGStringList>
45
SVGTests::SystemLanguage()
46
0
{
47
0
  return DOMSVGStringList::GetDOMWrapper(
48
0
           &mStringListAttributes[LANGUAGE], AsSVGElement(), true, LANGUAGE);
49
0
}
50
51
bool
52
SVGTests::HasExtension(const nsAString& aExtension)
53
0
{
54
0
  return nsSVGFeatures::HasExtension(aExtension,
55
0
                                     AsSVGElement()->IsInChromeDocument());
56
0
}
57
58
bool
59
SVGTests::IsConditionalProcessingAttribute(const nsAtom* aAttribute) const
60
0
{
61
0
  for (uint32_t i = 0; i < ArrayLength(sStringListNames); i++) {
62
0
    if (aAttribute == *sStringListNames[i]) {
63
0
      return true;
64
0
    }
65
0
  }
66
0
  return false;
67
0
}
68
69
int32_t
70
SVGTests::GetBestLanguagePreferenceRank(const nsAString& aAcceptLangs) const
71
0
{
72
0
  const nsCaseInsensitiveStringComparator caseInsensitiveComparator;
73
0
74
0
  if (!mStringListAttributes[LANGUAGE].IsExplicitlySet()) {
75
0
    return -2;
76
0
  }
77
0
78
0
  int32_t lowestRank = -1;
79
0
80
0
  for (uint32_t i = 0; i < mStringListAttributes[LANGUAGE].Length(); i++) {
81
0
    nsCharSeparatedTokenizer languageTokenizer(aAcceptLangs, ',');
82
0
    int32_t index = 0;
83
0
    while (languageTokenizer.hasMoreTokens()) {
84
0
      const nsAString& languageToken = languageTokenizer.nextToken();
85
0
      bool exactMatch = languageToken.Equals(mStringListAttributes[LANGUAGE][i],
86
0
                                             caseInsensitiveComparator);
87
0
      bool prefixOnlyMatch =
88
0
        !exactMatch &&
89
0
        nsStyleUtil::DashMatchCompare(mStringListAttributes[LANGUAGE][i],
90
0
                                      languageTokenizer.nextToken(),
91
0
                                      caseInsensitiveComparator);
92
0
      if (index == 0 && exactMatch) {
93
0
        // best possible match
94
0
        return 0;
95
0
      }
96
0
      if ((exactMatch || prefixOnlyMatch) &&
97
0
          (lowestRank == -1 || 2 * index + prefixOnlyMatch < lowestRank)) {
98
0
        lowestRank = 2 * index + prefixOnlyMatch;
99
0
      }
100
0
      ++index;
101
0
    }
102
0
  }
103
0
  return lowestRank;
104
0
}
105
106
const nsString * const SVGTests::kIgnoreSystemLanguage = (nsString *) 0x01;
107
108
bool
109
SVGTests::PassesConditionalProcessingTests(const nsString *aAcceptLangs) const
110
0
{
111
0
  // Required Extensions
112
0
  //
113
0
  // The requiredExtensions  attribute defines a list of required language
114
0
  // extensions. Language extensions are capabilities within a user agent that
115
0
  // go beyond the feature set defined in the SVG specification.
116
0
  // Each extension is identified by a URI reference.
117
0
  // For now, claim that mozilla's SVG implementation supports XHTML and MathML.
118
0
  if (mStringListAttributes[EXTENSIONS].IsExplicitlySet()) {
119
0
    if (mStringListAttributes[EXTENSIONS].IsEmpty()) {
120
0
      return false;
121
0
    }
122
0
    for (uint32_t i = 0; i < mStringListAttributes[EXTENSIONS].Length(); i++) {
123
0
      if (!nsSVGFeatures::HasExtension(mStringListAttributes[EXTENSIONS][i],
124
0
                                       AsSVGElement()->IsInChromeDocument())) {
125
0
        return false;
126
0
      }
127
0
    }
128
0
  }
129
0
130
0
  if (aAcceptLangs == kIgnoreSystemLanguage) {
131
0
    return true;
132
0
  }
133
0
134
0
  // systemLanguage
135
0
  //
136
0
  // Evaluates to "true" if one of the languages indicated by user preferences
137
0
  // exactly equals one of the languages given in the value of this parameter,
138
0
  // or if one of the languages indicated by user preferences exactly equals a
139
0
  // prefix of one of the languages given in the value of this parameter such
140
0
  // that the first tag character following the prefix is "-".
141
0
  if (mStringListAttributes[LANGUAGE].IsExplicitlySet()) {
142
0
    if (mStringListAttributes[LANGUAGE].IsEmpty()) {
143
0
      return false;
144
0
    }
145
0
146
0
    // Get our language preferences
147
0
    nsAutoString acceptLangs;
148
0
    if (aAcceptLangs) {
149
0
      acceptLangs.Assign(*aAcceptLangs);
150
0
    } else {
151
0
      Preferences::GetLocalizedString("intl.accept_languages", acceptLangs);
152
0
    }
153
0
154
0
    if (acceptLangs.IsEmpty()) {
155
0
      NS_WARNING("no default language specified for systemLanguage conditional test");
156
0
      return false;
157
0
    }
158
0
159
0
    const nsCaseInsensitiveStringComparator caseInsensitiveComparator;
160
0
161
0
    for (uint32_t i = 0; i < mStringListAttributes[LANGUAGE].Length(); i++) {
162
0
      nsCharSeparatedTokenizer languageTokenizer(acceptLangs, ',');
163
0
      while (languageTokenizer.hasMoreTokens()) {
164
0
        if (nsStyleUtil::DashMatchCompare(mStringListAttributes[LANGUAGE][i],
165
0
                                          languageTokenizer.nextToken(),
166
0
                                          caseInsensitiveComparator)) {
167
0
          return true;
168
0
        }
169
0
      }
170
0
    }
171
0
    return false;
172
0
  }
173
0
174
0
  return true;
175
0
}
176
177
bool
178
SVGTests::ParseConditionalProcessingAttribute(nsAtom* aAttribute,
179
                                              const nsAString& aValue,
180
                                              nsAttrValue& aResult)
181
0
{
182
0
  for (uint32_t i = 0; i < ArrayLength(sStringListNames); i++) {
183
0
    if (aAttribute == *sStringListNames[i]) {
184
0
      nsresult rv = mStringListAttributes[i].SetValue(aValue);
185
0
      if (NS_FAILED(rv)) {
186
0
        mStringListAttributes[i].Clear();
187
0
      }
188
0
      MaybeInvalidate();
189
0
      return true;
190
0
    }
191
0
  }
192
0
  return false;
193
0
}
194
195
void
196
SVGTests::UnsetAttr(const nsAtom* aAttribute)
197
0
{
198
0
  for (uint32_t i = 0; i < ArrayLength(sStringListNames); i++) {
199
0
    if (aAttribute == *sStringListNames[i]) {
200
0
      mStringListAttributes[i].Clear();
201
0
      MaybeInvalidate();
202
0
      return;
203
0
    }
204
0
  }
205
0
}
206
207
nsAtom*
208
SVGTests::GetAttrName(uint8_t aAttrEnum) const
209
0
{
210
0
  return *sStringListNames[aAttrEnum];
211
0
}
212
213
void
214
SVGTests::GetAttrValue(uint8_t aAttrEnum, nsAttrValue& aValue) const
215
0
{
216
0
  MOZ_ASSERT(aAttrEnum < ArrayLength(sStringListNames),
217
0
             "aAttrEnum out of range");
218
0
  aValue.SetTo(mStringListAttributes[aAttrEnum], nullptr);
219
0
}
220
221
void
222
SVGTests::MaybeInvalidate()
223
0
{
224
0
  nsIContent* parent = AsSVGElement()->GetFlattenedTreeParent();
225
0
226
0
  if (parent &&
227
0
      parent->NodeInfo()->Equals(nsGkAtoms::svgSwitch, kNameSpaceID_SVG)) {
228
0
    static_cast<dom::SVGSwitchElement*>(parent)->MaybeInvalidate();
229
0
  }
230
0
}
231
232
} // namespace dom
233
} // namespace mozilla