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 |