| 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 library validator_test; | 5 library validator_test; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:html'; | 8 import 'dart:html'; |
| 9 import 'dart:svg' as svg; | 9 import 'dart:svg' as svg; |
| 10 import 'package:unittest/unittest.dart'; | 10 import 'package:unittest/unittest.dart'; |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 checkUriPolicyCalls('q::cite', | 179 checkUriPolicyCalls('q::cite', |
| 180 '<q cite="s"></q>', | 180 '<q cite="s"></q>', |
| 181 '<q></q>', | 181 '<q></q>', |
| 182 ['s']); | 182 ['s']); |
| 183 checkUriPolicyCalls('video::poster', | 183 checkUriPolicyCalls('video::poster', |
| 184 '<video poster="s"/>', | 184 '<video poster="s"/>', |
| 185 '<video/>', | 185 '<video/>', |
| 186 ['s']); | 186 ['s']); |
| 187 }); | 187 }); |
| 188 | 188 |
| 189 group('NodeValidationPolicy', () { | 189 group('allowNavigation', () { |
| 190 | 190 var validator = new NodeValidatorBuilder()..allowNavigation(); |
| 191 group('allowNavigation', () { | 191 |
| 192 var validator = new NodeValidatorBuilder()..allowNavigation(); | 192 testHtml('allows anchor tags', |
| 193 | 193 validator, |
| 194 testHtml('allows anchor tags', | 194 '<a href="#foo">foo</a>'); |
| 195 |
| 196 testHtml('allows form elements', |
| 197 validator, |
| 198 '<form method="post" action="/foo"></form>'); |
| 199 |
| 200 testHtml('disallows script navigation', |
| 201 validator, |
| 202 '<a href="javascript:foo = 1">foo</a>', |
| 203 '<a>foo</a>'); |
| 204 |
| 205 testHtml('disallows cross-site navigation', |
| 206 validator, |
| 207 '<a href="http://example.com">example.com</a>', |
| 208 '<a>example.com</a>'); |
| 209 |
| 210 testHtml('blocks other elements', |
| 211 validator, |
| 212 '<a href="#foo"><b>foo</b></a>', |
| 213 '<a href="#foo"></a>'); |
| 214 |
| 215 testHtml('blocks tag extension', |
| 216 validator, |
| 217 '<a is="x-foo"></a>', |
| 218 ''); |
| 219 }); |
| 220 |
| 221 group('allowImages', () { |
| 222 var validator = new NodeValidatorBuilder()..allowImages(); |
| 223 |
| 224 testHtml('allows images', |
| 225 validator, |
| 226 '<img src="/foo.jpg" alt="something" width="100" height="100"/>'); |
| 227 |
| 228 testHtml('blocks onerror', |
| 229 validator, |
| 230 '<img src="/foo.jpg" onerror="something"/>', |
| 231 '<img src="/foo.jpg"/>'); |
| 232 |
| 233 testHtml('enforces same-origin', |
| 234 validator, |
| 235 '<img src="http://example.com/foo.jpg"/>', |
| 236 '<img/>'); |
| 237 }); |
| 238 |
| 239 group('allowCustomElement', () { |
| 240 var validator = new NodeValidatorBuilder() |
| 241 ..allowCustomElement( |
| 242 'x-foo', |
| 243 attributes: ['bar'], |
| 244 uriAttributes: ['baz']) |
| 245 ..allowHtml5(); |
| 246 |
| 247 testHtml('allows custom elements', |
| 248 validator, |
| 249 '<x-foo bar="something" baz="/foo.jpg"></x-foo>'); |
| 250 |
| 251 |
| 252 testHtml('validates custom tag URIs', |
| 253 validator, |
| 254 '<x-foo baz="http://example.com/foo.jpg"></x-foo>', |
| 255 '<x-foo></x-foo>'); |
| 256 |
| 257 testHtml('blocks type extensions', |
| 258 validator, |
| 259 '<div is="x-foo"></div>', |
| 260 ''); |
| 261 |
| 262 testHtml('blocks tags on non-matching elements', |
| 263 validator, |
| 264 '<div bar="foo"></div>', |
| 265 '<div></div>'); |
| 266 }); |
| 267 |
| 268 group('allowTagExtension', () { |
| 269 var validator = new NodeValidatorBuilder() |
| 270 ..allowTagExtension( |
| 271 'x-foo', |
| 272 'div', |
| 273 attributes: ['bar'], |
| 274 uriAttributes: ['baz']) |
| 275 ..allowHtml5(); |
| 276 |
| 277 testHtml('allows tag extensions', |
| 278 validator, |
| 279 '<div is="x-foo" bar="something" baz="/foo.jpg"></div>'); |
| 280 |
| 281 testHtml('blocks custom elements', |
| 195 validator, | 282 validator, |
| 196 '<a href="#foo">foo</a>'); | 283 '<x-foo></x-foo>', |
| 197 | |
| 198 testHtml('allows form elements', | |
| 199 validator, | |
| 200 '<form method="post" action="/foo"></form>'); | |
| 201 | |
| 202 testHtml('disallows script navigation', | |
| 203 validator, | |
| 204 '<a href="javascript:foo = 1">foo</a>', | |
| 205 '<a>foo</a>'); | |
| 206 | |
| 207 testHtml('disallows cross-site navigation', | |
| 208 validator, | |
| 209 '<a href="http://example.com">example.com</a>', | |
| 210 '<a>example.com</a>'); | |
| 211 | |
| 212 testHtml('blocks other elements', | |
| 213 validator, | |
| 214 '<a href="#foo"><b>foo</b></a>', | |
| 215 '<a href="#foo"></a>'); | |
| 216 | |
| 217 testHtml('blocks tag extension', | |
| 218 validator, | |
| 219 '<a is="x-foo"></a>', | |
| 220 ''); | 284 ''); |
| 221 }); | 285 |
| 222 | 286 testHtml('validates tag extension URIs', |
| 223 group('allowImages', () { | 287 validator, |
| 224 var validator = new NodeValidatorBuilder()..allowImages(); | 288 '<div is="x-foo" baz="http://example.com/foo.jpg"></div>', |
| 225 | 289 '<div is="x-foo"></div>'); |
| 226 testHtml('allows images', | 290 |
| 227 validator, | 291 testHtml('blocks tags on non-matching elements', |
| 228 '<img src="/foo.jpg" alt="something" width="100" height="100"/>'); | 292 validator, |
| 229 | 293 '<div bar="foo"></div>', |
| 230 testHtml('blocks onerror', | 294 '<div></div>'); |
| 231 validator, | 295 |
| 232 '<img src="/foo.jpg" onerror="something"/>', | 296 testHtml('blocks non-matching tags', |
| 233 '<img src="/foo.jpg"/>'); | 297 validator, |
| 234 | 298 '<span is="x-foo">something</span>', |
| 235 testHtml('enforces same-origin', | 299 ''); |
| 236 validator, | 300 |
| 237 '<img src="http://example.com/foo.jpg"/>', | 301 validator = new NodeValidatorBuilder() |
| 238 '<img/>'); | 302 ..allowTagExtension( |
| 239 }); | 303 'x-foo', |
| 240 | 304 'div', |
| 241 group('allowCustomElement', () { | 305 attributes: ['bar'], |
| 242 var validator = new NodeValidatorBuilder() | 306 uriAttributes: ['baz']) |
| 243 ..allowCustomElement( | 307 ..allowTagExtension( |
| 244 'x-foo', | 308 'x-else', |
| 245 attributes: ['bar'], | 309 'div'); |
| 246 uriAttributes: ['baz']) | 310 |
| 247 ..allowHtml5(); | 311 testHtml('blocks tags on non-matching custom elements', |
| 248 | 312 validator, |
| 249 testHtml('allows custom elements', | 313 '<div bar="foo" is="x-else"></div>', |
| 250 validator, | 314 '<div is="x-else"></div>'); |
| 251 '<x-foo bar="something" baz="/foo.jpg"></x-foo>'); | 315 }); |
| 252 | 316 |
| 253 | 317 group('allowTemplating', () { |
| 254 testHtml('validates custom tag URIs', | 318 var validator = new NodeValidatorBuilder() |
| 255 validator, | 319 ..allowTemplating() |
| 256 '<x-foo baz="http://example.com/foo.jpg"></x-foo>', | 320 ..allowHtml5(); |
| 257 '<x-foo></x-foo>'); | 321 |
| 258 | 322 testHtml('allows templates', |
| 259 testHtml('blocks type extensions', | 323 validator, |
| 260 validator, | 324 '<template bind="{{a}}"></template>'); |
| 261 '<div is="x-foo"></div>', | 325 |
| 262 ''); | 326 testHtml('allows template attributes', |
| 263 | 327 validator, |
| 264 testHtml('blocks tags on non-matching elements', | 328 '<template bind="{{a}}" ref="foo" repeat="{{}}" if="{{}}" syntax="foo"><
/template>'); |
| 265 validator, | 329 |
| 266 '<div bar="foo"></div>', | 330 testHtml('allows template attribute', |
| 267 '<div></div>'); | 331 validator, |
| 268 }); | 332 '<div template repeat="{{}}"></div>'); |
| 269 | 333 |
| 270 group('allowTagExtension', () { | 334 testHtml('blocks illegal template attribute', |
| 271 var validator = new NodeValidatorBuilder() | 335 validator, |
| 272 ..allowTagExtension( | 336 '<div template="foo" repeat="{{}}"></div>', |
| 273 'x-foo', | 337 '<div></div>'); |
| 274 'div', | 338 }); |
| 275 attributes: ['bar'], | 339 |
| 276 uriAttributes: ['baz']) | 340 group('allowSvg', () { |
| 277 ..allowHtml5(); | 341 var validator = new NodeValidatorBuilder() |
| 278 | 342 ..allowSvg() |
| 279 testHtml('allows tag extensions', | 343 ..allowTextElements(); |
| 280 validator, | 344 |
| 281 '<div is="x-foo" bar="something" baz="/foo.jpg"></div>'); | 345 testHtml('allows basic SVG', |
| 282 | 346 validator, |
| 283 testHtml('blocks custom elements', | 347 '<svg xmlns="http://www.w3.org/2000/svg' |
| 284 validator, | 348 'xmlns:xlink="http://www.w3.org/1999/xlink">' |
| 285 '<x-foo></x-foo>', | 349 '<image xlink:href="foo" data-foo="bar"/>' |
| 286 ''); | 350 '</svg>'); |
| 287 | 351 |
| 288 testHtml('validates tag extension URIs', | 352 testHtml('blocks script elements', |
| 289 validator, | 353 validator, |
| 290 '<div is="x-foo" baz="http://example.com/foo.jpg"></div>', | 354 '<svg xmlns="http://www.w3.org/2000/svg>' |
| 291 '<div is="x-foo"></div>'); | 355 '<script></script>' |
| 292 | 356 '</svg>', |
| 293 testHtml('blocks tags on non-matching elements', | 357 '<svg xmlns="http://www.w3.org/2000/svg></svg>'); |
| 294 validator, | 358 |
| 295 '<div bar="foo"></div>', | 359 testHtml('blocks script handlers', |
| 296 '<div></div>'); | 360 validator, |
| 297 | 361 '<svg xmlns="http://www.w3.org/2000/svg' |
| 298 testHtml('blocks non-matching tags', | 362 'xmlns:xlink="http://www.w3.org/1999/xlink">' |
| 299 validator, | 363 '<image xlink:href="foo" onerror="something"/>' |
| 300 '<span is="x-foo">something</span>', | 364 '</svg>', |
| 301 ''); | 365 '<svg xmlns="http://www.w3.org/2000/svg' |
| 302 | 366 'xmlns:xlink="http://www.w3.org/1999/xlink">' |
| 303 validator = new NodeValidatorBuilder() | 367 '<image xlink:href="foo"/>' |
| 304 ..allowTagExtension( | 368 '</svg>'); |
| 305 'x-foo', | 369 |
| 306 'div', | 370 testHtml('blocks foreignObject content', |
| 307 attributes: ['bar'], | 371 validator, |
| 308 uriAttributes: ['baz']) | 372 '<svg xmlns="http://www.w3.org/2000/svg">' |
| 309 ..allowTagExtension( | 373 '<foreignobject width="100" height="150">' |
| 310 'x-else', | 374 '<body xmlns="http://www.w3.org/1999/xhtml">' |
| 311 'div'); | 375 '<div>Some content</div>' |
| 312 | 376 '</body>' |
| 313 testHtml('blocks tags on non-matching custom elements', | 377 '</foreignobject>' |
| 314 validator, | 378 '<b>42</b>' |
| 315 '<div bar="foo" is="x-else"></div>', | 379 '</svg>', |
| 316 '<div is="x-else"></div>'); | 380 '<svg xmlns="http://www.w3.org/2000/svg">' |
| 317 }); | 381 '<b>42</b>' |
| 318 | 382 '</svg>'); |
| 319 group('allowTemplating', () { | 383 }); |
| 320 var validator = new NodeValidatorBuilder() | 384 |
| 321 ..allowTemplating() | 385 group('allowInlineStyles', () { |
| 322 ..allowHtml5(); | 386 var validator = new NodeValidatorBuilder() |
| 323 | 387 ..allowTextElements() |
| 324 testHtml('allows templates', | 388 ..allowInlineStyles(); |
| 325 validator, | 389 |
| 326 '<template bind="{{a}}"></template>'); | 390 testHtml('allows inline styles', |
| 327 | 391 validator, |
| 328 testHtml('allows template attributes', | 392 '<span style="background-color:red">text</span>'); |
| 329 validator, | 393 |
| 330 '<template bind="{{a}}" ref="foo" repeat="{{}}" if="{{}}" syntax="foo"
></template>'); | 394 testHtml('blocks other attributes', |
| 331 | 395 validator, |
| 332 testHtml('allows template attribute', | 396 '<span class="red-span"></span>', |
| 333 validator, | 397 '<span></span>'); |
| 334 '<div template repeat="{{}}"></div>'); | 398 |
| 335 | 399 validator = new NodeValidatorBuilder() |
| 336 testHtml('blocks illegal template attribute', | 400 ..allowTextElements() |
| 337 validator, | 401 ..allowInlineStyles(tagName: 'span'); |
| 338 '<div template="foo" repeat="{{}}"></div>', | 402 |
| 339 '<div></div>'); | 403 testHtml('scoped allows inline styles on spans', |
| 340 }); | 404 validator, |
| 341 | 405 '<span style="background-color:red">text</span>'); |
| 342 group('allowSvg', () { | 406 |
| 343 var validator = new NodeValidatorBuilder()..allowSvg(); | 407 testHtml('scoped blocks inline styles on LIs', |
| 344 | 408 validator, |
| 345 testHtml('allows basic SVG', | 409 '<li style="background-color:red">text</li>', |
| 346 validator, | 410 '<li>text</li>'); |
| 347 '<svg xmlns="http://www.w3.org/2000/svg' | |
| 348 'xmlns:xlink="http://www.w3.org/1999/xlink">' | |
| 349 '<image xlink:href="foo" data-foo="bar"/>' | |
| 350 '</svg>'); | |
| 351 | |
| 352 testHtml('blocks script elements', | |
| 353 validator, | |
| 354 '<svg xmlns="http://www.w3.org/2000/svg>' | |
| 355 '<script></script>' | |
| 356 '</svg>', | |
| 357 '<svg xmlns="http://www.w3.org/2000/svg></svg>'); | |
| 358 | |
| 359 testHtml('blocks script handlers', | |
| 360 validator, | |
| 361 '<svg xmlns="http://www.w3.org/2000/svg' | |
| 362 'xmlns:xlink="http://www.w3.org/1999/xlink">' | |
| 363 '<image xlink:href="foo" onerror="something"/>' | |
| 364 '</svg>', | |
| 365 '<svg xmlns="http://www.w3.org/2000/svg' | |
| 366 'xmlns:xlink="http://www.w3.org/1999/xlink">' | |
| 367 '<image xlink:href="foo"/>' | |
| 368 '</svg>'); | |
| 369 | |
| 370 testHtml('blocks foreignObject content', | |
| 371 validator, | |
| 372 '<svg xmlns="http://www.w3.org/2000/svg">' | |
| 373 '<foreignobject width="100" height="150">' | |
| 374 '<body xmlns="http://www.w3.org/1999/xhtml">' | |
| 375 '<div>Some content</div>' | |
| 376 '</body>' | |
| 377 '</foreignobject>' | |
| 378 '<number>42</number>' | |
| 379 '</svg>', | |
| 380 '<svg xmlns="http://www.w3.org/2000/svg">' | |
| 381 '<number>42</number>' | |
| 382 '</svg>'); | |
| 383 }); | |
| 384 | |
| 385 group('allowInlineStyles', () { | |
| 386 var validator = new NodeValidatorBuilder() | |
| 387 ..allowTextElements() | |
| 388 ..allowInlineStyles(); | |
| 389 | |
| 390 testHtml('allows inline styles', | |
| 391 validator, | |
| 392 '<span style="background-color:red">text</span>'); | |
| 393 | |
| 394 testHtml('blocks other attributes', | |
| 395 validator, | |
| 396 '<span class="red-span"></span>', | |
| 397 '<span></span>'); | |
| 398 | |
| 399 validator = new NodeValidatorBuilder() | |
| 400 ..allowTextElements() | |
| 401 ..allowInlineStyles(tagName: 'span'); | |
| 402 | |
| 403 testHtml('scoped allows inline styles on spans', | |
| 404 validator, | |
| 405 '<span style="background-color:red">text</span>'); | |
| 406 | |
| 407 testHtml('scoped blocks inline styles on LIs', | |
| 408 validator, | |
| 409 '<li style="background-color:red">text</li>', | |
| 410 '<li>text</li>'); | |
| 411 }); | |
| 412 }); | 411 }); |
| 413 | 412 |
| 414 group('throws', () { | 413 group('throws', () { |
| 415 var validator = new NodeValidator.throws(new NodeValidatorBuilder.common()); | 414 var validator = new NodeValidator.throws(new NodeValidatorBuilder.common()); |
| 416 | 415 |
| 417 var validationError = throwsArgumentError; | 416 var validationError = throwsArgumentError; |
| 418 | 417 |
| 419 test('does not throw on valid syntax', () { | 418 test('does not throw on valid syntax', () { |
| 420 expect(() { | 419 expect(() { |
| 421 document.body.createFragment('<div></div>', validator: validator); | 420 document.body.createFragment('<div></div>', validator: validator); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 451 '<image xlink:href="foo" data-foo="bar"/>' | 450 '<image xlink:href="foo" data-foo="bar"/>' |
| 452 '</svg>'; | 451 '</svg>'; |
| 453 | 452 |
| 454 var fragment = new DocumentFragment.svg(svgText); | 453 var fragment = new DocumentFragment.svg(svgText); |
| 455 var element = fragment.nodes.first; | 454 var element = fragment.nodes.first; |
| 456 expect(element is svg.SvgSvgElement, isTrue); | 455 expect(element is svg.SvgSvgElement, isTrue); |
| 457 expect(element.children[0] is svg.ImageElement, isTrue); | 456 expect(element.children[0] is svg.ImageElement, isTrue); |
| 458 }); | 457 }); |
| 459 }); | 458 }); |
| 460 } | 459 } |
| OLD | NEW |