Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(370)

Side by Side Diff: tests/html/node_validator_test.dart

Issue 16374007: First rev of Safe DOM (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tests/html/element_test.dart ('k') | tests/html/safe_dom_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library validator_test;
6
7 import 'dart:async';
8 import 'dart:html';
9 import 'dart:svg' as svg;
10 import 'package:unittest/unittest.dart';
11 import 'package:unittest/html_config.dart';
12 import 'utils.dart';
13
14
15 var nullSanitizer = new NullTreeSanitizer();
16
17 void validateHtml(String html, String reference, NodeValidator validator) {
18 var a = document.body.createFragment(html, validator: validator);
19 var b = document.body.createFragment(reference,
20 treeSanitizer: nullSanitizer);
21
22 validateNodeTree(a, b);
23 }
24
25 class RecordingUriValidator implements UriPolicy {
26 final List<String> calls = <String>[];
27
28 bool allowsUri(String uri) {
29 calls.add('$uri');
30 return false;
31 }
32
33 void reset() {
34 calls.clear();
35 }
36 }
37
38 void testHtml(String name, NodeValidator validator, String html,
39 [String reference]) {
40 test(name, () {
41 if (reference == null) {
42 reference = html;
43 }
44
45 validateHtml(html, reference, validator);
46 });
47 }
48
49 main() {
50 useHtmlConfiguration();
51
52 group('DOM sanitization', () {
53 var validator = new NodeValidatorBuilder.common();
54
55 testHtml('allows simple constructs',
56 validator,
57 '<div class="baz">something</div>');
58
59 testHtml('blocks unknown attributes',
60 validator,
61 '<div foo="baz">something</div>',
62 '<div>something</div>');
63
64 testHtml('blocks custom element',
65 validator,
66 '<x-my-element>something</x-my-element>',
67 '');
68
69 testHtml('blocks custom is element',
70 validator,
71 '<div is="x-my-element">something</div>',
72 '');
73
74 testHtml('blocks body elements',
75 validator,
76 '<body background="s"></body>',
77 '');
78
79 testHtml('allows select elements',
80 validator,
81 '<select>'
82 '<option>a</option>'
83 '</select>');
84
85 testHtml('blocks sequential script elements',
86 validator,
87 '<div><script></script><script></script></div>',
88 '<div></div>');
89
90 testHtml('blocks namespaced attributes',
91 validator,
92 '<div ns:foo="foo"></div>',
93 '<div></div>');
94
95 testHtml('blocks namespaced common attributes',
96 validator,
97 '<div ns:class="foo"></div>',
98 '<div></div>');
99
100 testHtml('blocks namespaced common elements',
101 validator,
102 '<ns:div></ns:div>',
103 '');
104
105 testHtml('allows CDATA sections',
106 validator,
107 '<span>![CDATA[ some text ]]></span>');
108
109 test('sanitizes template contents', () {
110 var html = '<template>'
111 '<div></div>'
112 '<script></script>'
113 '<img src="http://example.com/foo"/>'
114 '</template>';
115
116 var fragment = document.body.createFragment(html, validator: validator);
117 var template = fragment.nodes.single;
118
119 var expectedContent = document.body.createFragment(
120 '<div></div>'
121 '<img/>');
122
123 validateNodeTree(template.content, expectedContent);
124 });
125 });
126
127 group('URI sanitization', () {
128 var recorder = new RecordingUriValidator();
129 var validator = new NodeValidatorBuilder()..allowHtml5(uriPolicy: recorder);
130
131 checkUriPolicyCalls(String name, String html, String reference,
132 List<String> expectedCalls) {
133
134 test(name, () {
135 recorder.reset();
136
137 validateHtml(html, reference, validator);
138 expect(recorder.calls, expectedCalls);
139 });
140 }
141
142 checkUriPolicyCalls('a::href',
143 '<a href="s"></a>',
144 '<a></a>',
145 ['s']);
146
147 checkUriPolicyCalls('area::href',
148 '<area href="s"></area>',
149 '<area></area>',
150 ['s']);
151
152 checkUriPolicyCalls('blockquote::cite',
153 '<blockquote cite="s"></blockquote>',
154 '<blockquote></blockquote>',
155 ['s']);
156 checkUriPolicyCalls('command::icon',
157 '<command icon="s"/>',
158 '<command/>',
159 ['s']);
160 checkUriPolicyCalls('img::src',
161 '<img src="s"/>',
162 '<img/>',
163 ['s']);
164 checkUriPolicyCalls('input::src',
165 '<input src="s"/>',
166 '<input/>',
167 ['s']);
168 checkUriPolicyCalls('ins::cite',
169 '<ins cite="s"></ins>',
170 '<ins></ins>',
171 ['s']);
172 checkUriPolicyCalls('q::cite',
173 '<q cite="s"></q>',
174 '<q></q>',
175 ['s']);
176 checkUriPolicyCalls('video::poster',
177 '<video poster="s"/>',
178 '<video/>',
179 ['s']);
180 });
181
182 group('NodeValidationPolicy', () {
183
184 group('allowNavigation', () {
185 var validator = new NodeValidatorBuilder()..allowNavigation();
186
187 testHtml('allows anchor tags',
188 validator,
189 '<a href="#foo">foo</a>');
190
191 testHtml('allows form elements',
192 validator,
193 '<form method="post" action="/foo"></form>');
194
195 testHtml('disallows script navigation',
196 validator,
197 '<a href="javascript:foo = 1">foo</a>',
198 '<a>foo</a>');
199
200 testHtml('disallows cross-site navigation',
201 validator,
202 '<a href="http://example.com">example.com</a>',
203 '<a>example.com</a>');
204
205 testHtml('blocks other elements',
206 validator,
207 '<a href="#foo"><b>foo</b></a>',
208 '<a href="#foo"></a>');
209
210 testHtml('blocks tag extension',
211 validator,
212 '<a is="x-foo"></a>',
213 '');
214 });
215
216 group('allowImages', () {
217 var validator = new NodeValidatorBuilder()..allowImages();
218
219 testHtml('allows images',
220 validator,
221 '<img src="/foo.jpg" alt="something" width="100" height="100"/>');
222
223 testHtml('blocks onerror',
224 validator,
225 '<img src="/foo.jpg" onerror="something"/>',
226 '<img src="/foo.jpg"/>');
227
228 testHtml('enforces same-origin',
229 validator,
230 '<img src="http://example.com/foo.jpg"/>',
231 '<img/>');
232 });
233
234 group('allowCustomElement', () {
235 var validator = new NodeValidatorBuilder()
236 ..allowCustomElement(
237 'x-foo',
238 attributes: ['bar'],
239 uriAttributes: ['baz'])
240 ..allowHtml5();
241
242 testHtml('allows custom elements',
243 validator,
244 '<x-foo bar="something" baz="/foo.jpg"></x-foo>');
245
246
247 testHtml('validates custom tag URIs',
248 validator,
249 '<x-foo baz="http://example.com/foo.jpg"></x-foo>',
250 '<x-foo></x-foo>');
251
252 testHtml('blocks type extensions',
253 validator,
254 '<div is="x-foo"></div>',
255 '');
256
257 testHtml('blocks tags on non-matching elements',
258 validator,
259 '<div bar="foo"></div>',
260 '<div></div>');
261 });
262
263 group('allowTagExtension', () {
264 var validator = new NodeValidatorBuilder()
265 ..allowTagExtension(
266 'x-foo',
267 'div',
268 attributes: ['bar'],
269 uriAttributes: ['baz'])
270 ..allowHtml5();
271
272 testHtml('allows tag extensions',
273 validator,
274 '<div is="x-foo" bar="something" baz="/foo.jpg"></div>');
275
276 testHtml('blocks custom elements',
277 validator,
278 '<x-foo></x-foo>',
279 '');
280
281 testHtml('validates tag extension URIs',
282 validator,
283 '<div is="x-foo" baz="http://example.com/foo.jpg"></div>',
284 '<div is="x-foo"></div>');
285
286 testHtml('blocks tags on non-matching elements',
287 validator,
288 '<div bar="foo"></div>',
289 '<div></div>');
290
291 testHtml('blocks non-matching tags',
292 validator,
293 '<span is="x-foo">something</span>',
294 '');
295
296 validator = new NodeValidatorBuilder()
297 ..allowTagExtension(
298 'x-foo',
299 'div',
300 attributes: ['bar'],
301 uriAttributes: ['baz'])
302 ..allowTagExtension(
303 'x-else',
304 'div');
305
306 testHtml('blocks tags on non-matching custom elements',
307 validator,
308 '<div bar="foo" is="x-else"></div>',
309 '<div is="x-else"></div>');
310 });
311
312 group('allowTemplating', () {
313 var validator = new NodeValidatorBuilder()
314 ..allowTemplating()
315 ..allowHtml5();
316
317 testHtml('allows templates',
318 validator,
319 '<template bind="{{a}}"></template>');
320
321 testHtml('allows template attributes',
322 validator,
323 '<template bind="{{a}}" ref="foo" repeat="{{}}" if="{{}}" syntax="foo" ></template>');
324
325 testHtml('allows template attribute',
326 validator,
327 '<div template repeat="{{}}"></div>');
328
329 testHtml('blocks illegal template attribute',
330 validator,
331 '<div template="foo" repeat="{{}}"></div>',
332 '<div></div>');
333 });
334
335 group('allowSvg', () {
336 var validator = new NodeValidatorBuilder()..allowSvg();
337
338 testHtml('allows basic SVG',
339 validator,
340 '<svg xmlns="http://www.w3.org/2000/svg'
341 'xmlns:xlink="http://www.w3.org/1999/xlink">'
342 '<image xlink:href="foo" data-foo="bar"/>'
343 '</svg>');
344
345 testHtml('blocks script elements',
346 validator,
347 '<svg xmlns="http://www.w3.org/2000/svg>'
348 '<script></script>'
349 '</svg>',
350 '<svg xmlns="http://www.w3.org/2000/svg></svg>');
351
352 testHtml('blocks script handlers',
353 validator,
354 '<svg xmlns="http://www.w3.org/2000/svg'
355 'xmlns:xlink="http://www.w3.org/1999/xlink">'
356 '<image xlink:href="foo" onerror="something"/>'
357 '</svg>',
358 '<svg xmlns="http://www.w3.org/2000/svg'
359 'xmlns:xlink="http://www.w3.org/1999/xlink">'
360 '<image xlink:href="foo"/>'
361 '</svg>');
362
363 testHtml('blocks foreignObject content',
364 validator,
365 '<svg xmlns="http://www.w3.org/2000/svg>'
366 '<foreignobject width="100" height="150">'
367 '<body xmlns="http://www.w3.org/1999/xhtml">'
368 '<div>Some content</div>'
369 '</body>'
370 '</foreignobject>'
371 '</svg>',
372 '<svg xmlns="http://www.w3.org/2000/svg>'
373 '<foreignobject width="100" height="150"></foreignobject>'
374 '</svg>');
375 });
376 });
377
378 group('throws', () {
379 var validator = new NodeValidator.throws(new NodeValidatorBuilder.common());
380
381 var validationError = throwsArgumentError;
382
383 test('does not throw on valid syntax', () {
384 expect(() {
385 document.body.createFragment('<div></div>', validator: validator);
386 }, returnsNormally);
387 });
388
389 test('throws on invalid elements', () {
390 expect(() {
391 document.body.createFragment('<foo></foo>', validator: validator);
392 }, validationError);
393 });
394
395 test('throws on invalid attributes', () {
396 expect(() {
397 document.body.createFragment('<div foo="bar"></div>',
398 validator: validator);
399 }, validationError);
400 });
401
402 test('throws on invalid attribute values', () {
403 expect(() {
404 document.body.createFragment('<img src="http://example.com/foo.jpg"/>',
405 validator: validator);
406 }, validationError);
407 });
408 });
409
410 group('svg', () {
411 test('parsing', () {
412 var svgText =
413 '<svg xmlns="http://www.w3.org/2000/svg'
414 'xmlns:xlink="http://www.w3.org/1999/xlink">'
415 '<image xlink:href="foo" data-foo="bar"/>'
416 '</svg>';
417
418 var fragment = new DocumentFragment.svg(svgText);
419 var element = fragment.nodes.first;
420 expect(element is svg.SvgSvgElement, isTrue);
421 expect(element.children[0] is svg.ImageElement, isTrue);
422 });
423 });
424 }
OLDNEW
« no previous file with comments | « tests/html/element_test.dart ('k') | tests/html/safe_dom_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698