| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.dom.html; | 5 part of dart.dom.html; |
| 6 | 6 |
| 7 | |
| 8 /** | 7 /** |
| 9 * Class which helps construct standard node validation policies. | 8 * Class which helps construct standard node validation policies. |
| 10 * | 9 * |
| 11 * By default this will not accept anything, but the 'allow*' functions can be | 10 * By default this will not accept anything, but the 'allow*' functions can be |
| 12 * used to expand what types of elements or attributes are allowed. | 11 * used to expand what types of elements or attributes are allowed. |
| 13 * | 12 * |
| 14 * All allow functions are additive- elements will be accepted if they are | 13 * All allow functions are additive- elements will be accepted if they are |
| 15 * accepted by any specific rule. | 14 * accepted by any specific rule. |
| 16 * | 15 * |
| 17 * It is important to remember that sanitization is not just intended to prevent | 16 * It is important to remember that sanitization is not just intended to prevent |
| 18 * cross-site scripting attacks, but also to prevent information from being | 17 * cross-site scripting attacks, but also to prevent information from being |
| 19 * displayed in unexpected ways. For example something displaying basic | 18 * displayed in unexpected ways. For example something displaying basic |
| 20 * formatted text may not expect `<video>` tags to appear. In this case an | 19 * formatted text may not expect `<video>` tags to appear. In this case an |
| 21 * empty NodeValidatorBuilder with just [allowTextElements] might be | 20 * empty NodeValidatorBuilder with just [allowTextElements] might be |
| 22 * appropriate. | 21 * appropriate. |
| 23 */ | 22 */ |
| 24 class NodeValidatorBuilder implements NodeValidator { | 23 class NodeValidatorBuilder implements NodeValidator { |
| 25 | |
| 26 final List<NodeValidator> _validators = <NodeValidator>[]; | 24 final List<NodeValidator> _validators = <NodeValidator>[]; |
| 27 | 25 |
| 28 NodeValidatorBuilder() { | 26 NodeValidatorBuilder() {} |
| 29 } | |
| 30 | 27 |
| 31 /** | 28 /** |
| 32 * Creates a new NodeValidatorBuilder which accepts common constructs. | 29 * Creates a new NodeValidatorBuilder which accepts common constructs. |
| 33 * | 30 * |
| 34 * By default this will accept HTML5 elements and attributes with the default | 31 * By default this will accept HTML5 elements and attributes with the default |
| 35 * [UriPolicy] and templating elements. | 32 * [UriPolicy] and templating elements. |
| 36 * | 33 * |
| 37 * Notable syntax which is filtered: | 34 * Notable syntax which is filtered: |
| 38 * | 35 * |
| 39 * * Only known-good HTML5 elements and attributes are allowed. | 36 * * Only known-good HTML5 elements and attributes are allowed. |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 * Allow custom elements with the specified tag name and specified attributes. | 145 * Allow custom elements with the specified tag name and specified attributes. |
| 149 * | 146 * |
| 150 * This will allow the elements as custom tags (such as <x-foo></x-foo>), | 147 * This will allow the elements as custom tags (such as <x-foo></x-foo>), |
| 151 * but will not allow tag extensions. Use [allowTagExtension] to allow | 148 * but will not allow tag extensions. Use [allowTagExtension] to allow |
| 152 * tag extensions. | 149 * tag extensions. |
| 153 */ | 150 */ |
| 154 void allowCustomElement(String tagName, | 151 void allowCustomElement(String tagName, |
| 155 {UriPolicy uriPolicy, | 152 {UriPolicy uriPolicy, |
| 156 Iterable<String> attributes, | 153 Iterable<String> attributes, |
| 157 Iterable<String> uriAttributes}) { | 154 Iterable<String> uriAttributes}) { |
| 158 | |
| 159 var tagNameUpper = tagName.toUpperCase(); | 155 var tagNameUpper = tagName.toUpperCase(); |
| 160 var attrs; | 156 var attrs = attributes |
| 161 if (attributes != null) { | 157 ?.map /*<String>*/ ((name) => '$tagNameUpper::${name.toLowerCase()}'); |
| 162 attrs = | 158 var uriAttrs = uriAttributes |
| 163 attributes.map((name) => '$tagNameUpper::${name.toLowerCase()}'); | 159 ?.map /*<String>*/ ((name) => '$tagNameUpper::${name.toLowerCase()}'); |
| 164 } | |
| 165 var uriAttrs; | |
| 166 if (uriAttributes != null) { | |
| 167 uriAttrs = | |
| 168 uriAttributes.map((name) => '$tagNameUpper::${name.toLowerCase()}'); | |
| 169 } | |
| 170 if (uriPolicy == null) { | 160 if (uriPolicy == null) { |
| 171 uriPolicy = new UriPolicy(); | 161 uriPolicy = new UriPolicy(); |
| 172 } | 162 } |
| 173 | 163 |
| 174 add(new _CustomElementNodeValidator( | 164 add(new _CustomElementNodeValidator( |
| 175 uriPolicy, | 165 uriPolicy, [tagNameUpper], attrs, uriAttrs, false, true)); |
| 176 [tagNameUpper], | |
| 177 attrs, | |
| 178 uriAttrs, | |
| 179 false, | |
| 180 true)); | |
| 181 } | 166 } |
| 182 | 167 |
| 183 /** | 168 /** |
| 184 * Allow custom tag extensions with the specified type name and specified | 169 * Allow custom tag extensions with the specified type name and specified |
| 185 * attributes. | 170 * attributes. |
| 186 * | 171 * |
| 187 * This will allow tag extensions (such as <div is="x-foo"></div>), | 172 * This will allow tag extensions (such as <div is="x-foo"></div>), |
| 188 * but will not allow custom tags. Use [allowCustomElement] to allow | 173 * but will not allow custom tags. Use [allowCustomElement] to allow |
| 189 * custom tags. | 174 * custom tags. |
| 190 */ | 175 */ |
| 191 void allowTagExtension(String tagName, String baseName, | 176 void allowTagExtension(String tagName, String baseName, |
| 192 {UriPolicy uriPolicy, | 177 {UriPolicy uriPolicy, |
| 193 Iterable<String> attributes, | 178 Iterable<String> attributes, |
| 194 Iterable<String> uriAttributes}) { | 179 Iterable<String> uriAttributes}) { |
| 195 | |
| 196 var baseNameUpper = baseName.toUpperCase(); | 180 var baseNameUpper = baseName.toUpperCase(); |
| 197 var tagNameUpper = tagName.toUpperCase(); | 181 var tagNameUpper = tagName.toUpperCase(); |
| 198 var attrs; | 182 var attrs = attributes |
| 199 if (attributes != null) { | 183 ?.map /*<String>*/ ((name) => '$baseNameUpper::${name.toLowerCase()}'); |
| 200 attrs = | 184 var uriAttrs = uriAttributes |
| 201 attributes.map((name) => '$baseNameUpper::${name.toLowerCase()}'); | 185 ?.map /*<String>*/ ((name) => '$baseNameUpper::${name.toLowerCase()}'); |
| 202 } | |
| 203 var uriAttrs; | |
| 204 if (uriAttributes != null) { | |
| 205 uriAttrs = | |
| 206 uriAttributes.map((name) => '$baseNameUpper::${name.toLowerCase()}'); | |
| 207 } | |
| 208 if (uriPolicy == null) { | 186 if (uriPolicy == null) { |
| 209 uriPolicy = new UriPolicy(); | 187 uriPolicy = new UriPolicy(); |
| 210 } | 188 } |
| 211 | 189 |
| 212 add(new _CustomElementNodeValidator( | 190 add(new _CustomElementNodeValidator(uriPolicy, |
| 213 uriPolicy, | 191 [tagNameUpper, baseNameUpper], attrs, uriAttrs, true, false)); |
| 214 [tagNameUpper, baseNameUpper], | |
| 215 attrs, | |
| 216 uriAttrs, | |
| 217 true, | |
| 218 false)); | |
| 219 } | 192 } |
| 220 | 193 |
| 221 void allowElement(String tagName, {UriPolicy uriPolicy, | 194 void allowElement(String tagName, |
| 222 Iterable<String> attributes, | 195 {UriPolicy uriPolicy, |
| 223 Iterable<String> uriAttributes}) { | 196 Iterable<String> attributes, |
| 224 | 197 Iterable<String> uriAttributes}) { |
| 225 allowCustomElement(tagName, uriPolicy: uriPolicy, | 198 allowCustomElement(tagName, |
| 199 uriPolicy: uriPolicy, |
| 226 attributes: attributes, | 200 attributes: attributes, |
| 227 uriAttributes: uriAttributes); | 201 uriAttributes: uriAttributes); |
| 228 } | 202 } |
| 229 | 203 |
| 230 /** | 204 /** |
| 231 * Allow templating elements (such as <template> and template-related | 205 * Allow templating elements (such as <template> and template-related |
| 232 * attributes. | 206 * attributes. |
| 233 * | 207 * |
| 234 * This still requires other validators to allow regular attributes to be | 208 * This still requires other validators to allow regular attributes to be |
| 235 * bound (such as [allowHtml5]). | 209 * bound (such as [allowHtml5]). |
| (...skipping 10 matching lines...) Expand all Loading... |
| 246 */ | 220 */ |
| 247 void add(NodeValidator validator) { | 221 void add(NodeValidator validator) { |
| 248 _validators.add(validator); | 222 _validators.add(validator); |
| 249 } | 223 } |
| 250 | 224 |
| 251 bool allowsElement(Element element) { | 225 bool allowsElement(Element element) { |
| 252 return _validators.any((v) => v.allowsElement(element)); | 226 return _validators.any((v) => v.allowsElement(element)); |
| 253 } | 227 } |
| 254 | 228 |
| 255 bool allowsAttribute(Element element, String attributeName, String value) { | 229 bool allowsAttribute(Element element, String attributeName, String value) { |
| 256 return _validators.any( | 230 return _validators |
| 257 (v) => v.allowsAttribute(element, attributeName, value)); | 231 .any((v) => v.allowsAttribute(element, attributeName, value)); |
| 258 } | 232 } |
| 259 } | 233 } |
| 260 | 234 |
| 261 class _SimpleNodeValidator implements NodeValidator { | 235 class _SimpleNodeValidator implements NodeValidator { |
| 262 final Set<String> allowedElements = new Set<String>(); | 236 final Set<String> allowedElements = new Set<String>(); |
| 263 final Set<String> allowedAttributes = new Set<String>(); | 237 final Set<String> allowedAttributes = new Set<String>(); |
| 264 final Set<String> allowedUriAttributes = new Set<String>(); | 238 final Set<String> allowedUriAttributes = new Set<String>(); |
| 265 final UriPolicy uriPolicy; | 239 final UriPolicy uriPolicy; |
| 266 | 240 |
| 267 factory _SimpleNodeValidator.allowNavigation(UriPolicy uriPolicy) { | 241 factory _SimpleNodeValidator.allowNavigation(UriPolicy uriPolicy) { |
| 268 return new _SimpleNodeValidator(uriPolicy, | 242 return new _SimpleNodeValidator(uriPolicy, allowedElements: const [ |
| 269 allowedElements: const [ | 243 'A', |
| 270 'A', | 244 'FORM' |
| 271 'FORM'], | 245 ], allowedAttributes: const [ |
| 272 allowedAttributes: const [ | 246 'A::accesskey', |
| 273 'A::accesskey', | 247 'A::coords', |
| 274 'A::coords', | 248 'A::hreflang', |
| 275 'A::hreflang', | 249 'A::name', |
| 276 'A::name', | 250 'A::shape', |
| 277 'A::shape', | 251 'A::tabindex', |
| 278 'A::tabindex', | 252 'A::target', |
| 279 'A::target', | 253 'A::type', |
| 280 'A::type', | 254 'FORM::accept', |
| 281 'FORM::accept', | 255 'FORM::autocomplete', |
| 282 'FORM::autocomplete', | 256 'FORM::enctype', |
| 283 'FORM::enctype', | 257 'FORM::method', |
| 284 'FORM::method', | 258 'FORM::name', |
| 285 'FORM::name', | 259 'FORM::novalidate', |
| 286 'FORM::novalidate', | 260 'FORM::target', |
| 287 'FORM::target', | 261 ], allowedUriAttributes: const [ |
| 288 ], | 262 'A::href', |
| 289 allowedUriAttributes: const [ | 263 'FORM::action', |
| 290 'A::href', | 264 ]); |
| 291 'FORM::action', | |
| 292 ]); | |
| 293 } | 265 } |
| 294 | 266 |
| 295 factory _SimpleNodeValidator.allowImages(UriPolicy uriPolicy) { | 267 factory _SimpleNodeValidator.allowImages(UriPolicy uriPolicy) { |
| 296 return new _SimpleNodeValidator(uriPolicy, | 268 return new _SimpleNodeValidator(uriPolicy, allowedElements: const [ |
| 297 allowedElements: const [ | 269 'IMG' |
| 298 'IMG' | 270 ], allowedAttributes: const [ |
| 299 ], | 271 'IMG::align', |
| 300 allowedAttributes: const [ | 272 'IMG::alt', |
| 301 'IMG::align', | 273 'IMG::border', |
| 302 'IMG::alt', | 274 'IMG::height', |
| 303 'IMG::border', | 275 'IMG::hspace', |
| 304 'IMG::height', | 276 'IMG::ismap', |
| 305 'IMG::hspace', | 277 'IMG::name', |
| 306 'IMG::ismap', | 278 'IMG::usemap', |
| 307 'IMG::name', | 279 'IMG::vspace', |
| 308 'IMG::usemap', | 280 'IMG::width', |
| 309 'IMG::vspace', | 281 ], allowedUriAttributes: const [ |
| 310 'IMG::width', | 282 'IMG::src', |
| 311 ], | 283 ]); |
| 312 allowedUriAttributes: const [ | |
| 313 'IMG::src', | |
| 314 ]); | |
| 315 } | 284 } |
| 316 | 285 |
| 317 factory _SimpleNodeValidator.allowTextElements() { | 286 factory _SimpleNodeValidator.allowTextElements() { |
| 318 return new _SimpleNodeValidator(null, | 287 return new _SimpleNodeValidator(null, allowedElements: const [ |
| 319 allowedElements: const [ | 288 'B', |
| 320 'B', | 289 'BLOCKQUOTE', |
| 321 'BLOCKQUOTE', | 290 'BR', |
| 322 'BR', | 291 'EM', |
| 323 'EM', | 292 'H1', |
| 324 'H1', | 293 'H2', |
| 325 'H2', | 294 'H3', |
| 326 'H3', | 295 'H4', |
| 327 'H4', | 296 'H5', |
| 328 'H5', | 297 'H6', |
| 329 'H6', | 298 'HR', |
| 330 'HR', | 299 'I', |
| 331 'I', | 300 'LI', |
| 332 'LI', | 301 'OL', |
| 333 'OL', | 302 'P', |
| 334 'P', | 303 'SPAN', |
| 335 'SPAN', | 304 'UL', |
| 336 'UL', | 305 ]); |
| 337 ]); | |
| 338 } | 306 } |
| 339 | 307 |
| 340 /** | 308 /** |
| 341 * Elements must be uppercased tag names. For example `'IMG'`. | 309 * Elements must be uppercased tag names. For example `'IMG'`. |
| 342 * Attributes must be uppercased tag name followed by :: followed by | 310 * Attributes must be uppercased tag name followed by :: followed by |
| 343 * lowercase attribute name. For example `'IMG:src'`. | 311 * lowercase attribute name. For example `'IMG:src'`. |
| 344 */ | 312 */ |
| 345 _SimpleNodeValidator(this.uriPolicy, | 313 _SimpleNodeValidator(this.uriPolicy, |
| 346 {Iterable<String> allowedElements, Iterable<String> allowedAttributes, | 314 {Iterable<String> allowedElements, |
| 347 Iterable<String> allowedUriAttributes}) { | 315 Iterable<String> allowedAttributes, |
| 316 Iterable<String> allowedUriAttributes}) { |
| 348 this.allowedElements.addAll(allowedElements ?? const []); | 317 this.allowedElements.addAll(allowedElements ?? const []); |
| 349 allowedAttributes = allowedAttributes ?? const []; | 318 allowedAttributes = allowedAttributes ?? const []; |
| 350 allowedUriAttributes = allowedUriAttributes ?? const []; | 319 allowedUriAttributes = allowedUriAttributes ?? const []; |
| 351 var legalAttributes = allowedAttributes.where( | 320 var legalAttributes = allowedAttributes |
| 352 (x) => !_Html5NodeValidator._uriAttributes.contains(x)); | 321 .where((x) => !_Html5NodeValidator._uriAttributes.contains(x)); |
| 353 var extraUriAttributes = allowedAttributes.where( | 322 var extraUriAttributes = allowedAttributes |
| 354 (x) => _Html5NodeValidator._uriAttributes.contains(x)); | 323 .where((x) => _Html5NodeValidator._uriAttributes.contains(x)); |
| 355 this.allowedAttributes.addAll(legalAttributes); | 324 this.allowedAttributes.addAll(legalAttributes); |
| 356 this.allowedUriAttributes.addAll(allowedUriAttributes); | 325 this.allowedUriAttributes.addAll(allowedUriAttributes); |
| 357 this.allowedUriAttributes.addAll(extraUriAttributes); | 326 this.allowedUriAttributes.addAll(extraUriAttributes); |
| 358 } | 327 } |
| 359 | 328 |
| 360 bool allowsElement(Element element) { | 329 bool allowsElement(Element element) { |
| 361 return allowedElements.contains(Element._safeTagName(element)); | 330 return allowedElements.contains(Element._safeTagName(element)); |
| 362 } | 331 } |
| 363 | 332 |
| 364 bool allowsAttribute(Element element, String attributeName, String value) { | 333 bool allowsAttribute(Element element, String attributeName, String value) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 377 return true; | 346 return true; |
| 378 } | 347 } |
| 379 return false; | 348 return false; |
| 380 } | 349 } |
| 381 } | 350 } |
| 382 | 351 |
| 383 class _CustomElementNodeValidator extends _SimpleNodeValidator { | 352 class _CustomElementNodeValidator extends _SimpleNodeValidator { |
| 384 final bool allowTypeExtension; | 353 final bool allowTypeExtension; |
| 385 final bool allowCustomTag; | 354 final bool allowCustomTag; |
| 386 | 355 |
| 387 _CustomElementNodeValidator(UriPolicy uriPolicy, | 356 _CustomElementNodeValidator( |
| 357 UriPolicy uriPolicy, |
| 388 Iterable<String> allowedElements, | 358 Iterable<String> allowedElements, |
| 389 Iterable<String> allowedAttributes, | 359 Iterable<String> allowedAttributes, |
| 390 Iterable<String> allowedUriAttributes, | 360 Iterable<String> allowedUriAttributes, |
| 391 bool allowTypeExtension, | 361 bool allowTypeExtension, |
| 392 bool allowCustomTag): | 362 bool allowCustomTag) |
| 393 | 363 : this.allowTypeExtension = allowTypeExtension == true, |
| 394 super(uriPolicy, | 364 this.allowCustomTag = allowCustomTag == true, |
| 395 allowedElements: allowedElements, | 365 super(uriPolicy, |
| 396 allowedAttributes: allowedAttributes, | 366 allowedElements: allowedElements, |
| 397 allowedUriAttributes: allowedUriAttributes), | 367 allowedAttributes: allowedAttributes, |
| 398 this.allowTypeExtension = allowTypeExtension == true, | 368 allowedUriAttributes: allowedUriAttributes); |
| 399 this.allowCustomTag = allowCustomTag == true; | |
| 400 | 369 |
| 401 bool allowsElement(Element element) { | 370 bool allowsElement(Element element) { |
| 402 if (allowTypeExtension) { | 371 if (allowTypeExtension) { |
| 403 var isAttr = element.attributes['is']; | 372 var isAttr = element.attributes['is']; |
| 404 if (isAttr != null) { | 373 if (isAttr != null) { |
| 405 return allowedElements.contains(isAttr.toUpperCase()) && | 374 return allowedElements.contains(isAttr.toUpperCase()) && |
| 406 allowedElements.contains(Element._safeTagName(element)); | 375 allowedElements.contains(Element._safeTagName(element)); |
| 407 } | 376 } |
| 408 } | 377 } |
| 409 return allowCustomTag && allowedElements.contains(Element._safeTagName(eleme
nt)); | 378 return allowCustomTag && |
| 379 allowedElements.contains(Element._safeTagName(element)); |
| 410 } | 380 } |
| 411 | 381 |
| 412 bool allowsAttribute(Element element, String attributeName, String value) { | 382 bool allowsAttribute(Element element, String attributeName, String value) { |
| 413 if (allowsElement(element)) { | 383 if (allowsElement(element)) { |
| 414 if (allowTypeExtension && attributeName == 'is' && | 384 if (allowTypeExtension && |
| 385 attributeName == 'is' && |
| 415 allowedElements.contains(value.toUpperCase())) { | 386 allowedElements.contains(value.toUpperCase())) { |
| 416 return true; | 387 return true; |
| 417 } | 388 } |
| 418 return super.allowsAttribute(element, attributeName, value); | 389 return super.allowsAttribute(element, attributeName, value); |
| 419 } | 390 } |
| 420 return false; | 391 return false; |
| 421 } | 392 } |
| 422 } | 393 } |
| 423 | 394 |
| 424 class _TemplatingNodeValidator extends _SimpleNodeValidator { | 395 class _TemplatingNodeValidator extends _SimpleNodeValidator { |
| 425 static const _TEMPLATE_ATTRS = | 396 static const _TEMPLATE_ATTRS = const <String>[ |
| 426 const <String>['bind', 'if', 'ref', 'repeat', 'syntax']; | 397 'bind', |
| 398 'if', |
| 399 'ref', |
| 400 'repeat', |
| 401 'syntax' |
| 402 ]; |
| 427 | 403 |
| 428 final Set<String> _templateAttrs; | 404 final Set<String> _templateAttrs; |
| 429 | 405 |
| 430 _TemplatingNodeValidator(): | 406 _TemplatingNodeValidator() |
| 431 super(null, | 407 : _templateAttrs = new Set<String>.from(_TEMPLATE_ATTRS), |
| 432 allowedElements: [ | 408 super(null, |
| 433 'TEMPLATE' | 409 allowedElements: ['TEMPLATE'], |
| 434 ], | 410 allowedAttributes: |
| 435 allowedAttributes: _TEMPLATE_ATTRS.map((attr) => 'TEMPLATE::$attr')), | 411 _TEMPLATE_ATTRS.map((attr) => 'TEMPLATE::$attr')) {} |
| 436 _templateAttrs = new Set<String>.from(_TEMPLATE_ATTRS) { | |
| 437 } | |
| 438 | 412 |
| 439 bool allowsAttribute(Element element, String attributeName, String value) { | 413 bool allowsAttribute(Element element, String attributeName, String value) { |
| 440 if (super.allowsAttribute(element, attributeName, value)) { | 414 if (super.allowsAttribute(element, attributeName, value)) { |
| 441 return true; | 415 return true; |
| 442 } | 416 } |
| 443 | 417 |
| 444 if (attributeName == 'template' && value == "") { | 418 if (attributeName == 'template' && value == "") { |
| 445 return true; | 419 return true; |
| 446 } | 420 } |
| 447 | 421 |
| 448 if (element.attributes['template'] == "" ) { | 422 if (element.attributes['template'] == "") { |
| 449 return _templateAttrs.contains(attributeName); | 423 return _templateAttrs.contains(attributeName); |
| 450 } | 424 } |
| 451 return false; | 425 return false; |
| 452 } | 426 } |
| 453 } | 427 } |
| 454 | 428 |
| 455 | |
| 456 class _SvgNodeValidator implements NodeValidator { | 429 class _SvgNodeValidator implements NodeValidator { |
| 457 bool allowsElement(Element element) { | 430 bool allowsElement(Element element) { |
| 458 if (element is svg.ScriptElement) { | 431 if (element is svg.ScriptElement) { |
| 459 return false; | 432 return false; |
| 460 } | 433 } |
| 461 // Firefox 37 has issues with creating foreign elements inside a | 434 // Firefox 37 has issues with creating foreign elements inside a |
| 462 // foreignobject tag as SvgElement. We don't want foreignobject contents | 435 // foreignobject tag as SvgElement. We don't want foreignobject contents |
| 463 // anyway, so just remove the whole tree outright. And we can't rely | 436 // anyway, so just remove the whole tree outright. And we can't rely |
| 464 // on IE recognizing the SvgForeignObject type, so go by tagName. Bug 23144 | 437 // on IE recognizing the SvgForeignObject type, so go by tagName. Bug 23144 |
| 465 if (element is svg.SvgElement && Element._safeTagName(element) == 'foreignOb
ject') { | 438 if (element is svg.SvgElement && |
| 439 Element._safeTagName(element) == 'foreignObject') { |
| 466 return false; | 440 return false; |
| 467 } | 441 } |
| 468 if (element is svg.SvgElement) { | 442 if (element is svg.SvgElement) { |
| 469 return true; | 443 return true; |
| 470 } | 444 } |
| 471 return false; | 445 return false; |
| 472 } | 446 } |
| 473 | 447 |
| 474 bool allowsAttribute(Element element, String attributeName, String value) { | 448 bool allowsAttribute(Element element, String attributeName, String value) { |
| 475 if (attributeName == 'is' || attributeName.startsWith('on')) { | 449 if (attributeName == 'is' || attributeName.startsWith('on')) { |
| 476 return false; | 450 return false; |
| 477 } | 451 } |
| 478 return allowsElement(element); | 452 return allowsElement(element); |
| 479 } | 453 } |
| 480 } | 454 } |
| OLD | NEW |