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

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, 6 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
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
110 group('URI sanitization', () {
111 var recorder = new RecordingUriValidator();
112 var validator = new NodeValidatorBuilder()..allowHtml5(uriPolicy: recorder);
113
114 checkUriPolicyCalls(String name, String html, String reference,
115 List<String> expectedCalls) {
116
117 test(name, () {
118 recorder.reset();
119
120 validateHtml(html, reference, validator);
121 expect(recorder.calls, expectedCalls);
122 });
123 }
124
125 checkUriPolicyCalls('a::href',
126 '<a href="s"></a>',
127 '<a></a>',
128 ['s']);
129
130 checkUriPolicyCalls('area::href',
131 '<area href="s"></area>',
132 '<area></area>',
133 ['s']);
134
135 checkUriPolicyCalls('blockquote::cite',
136 '<blockquote cite="s"></blockquote>',
137 '<blockquote></blockquote>',
138 ['s']);
139 checkUriPolicyCalls('command::icon',
140 '<command icon="s"/>',
141 '<command/>',
142 ['s']);
143 checkUriPolicyCalls('img::src',
144 '<img src="s"/>',
145 '<img/>',
146 ['s']);
147 checkUriPolicyCalls('input::src',
148 '<input src="s"/>',
149 '<input/>',
150 ['s']);
151 checkUriPolicyCalls('ins::cite',
152 '<ins cite="s"></ins>',
153 '<ins></ins>',
154 ['s']);
155 checkUriPolicyCalls('q::cite',
156 '<q cite="s"></q>',
157 '<q></q>',
158 ['s']);
159 checkUriPolicyCalls('video::poster',
160 '<video poster="s"/>',
161 '<video/>',
162 ['s']);
163 });
164
165 group('NodeValidationPolicy', () {
166
167 group('allowNavigation', () {
168 var validator = new NodeValidatorBuilder()..allowNavigation();
169
170 testHtml('allows anchor tags',
171 validator,
172 '<a href="#foo">foo</a>');
173
174 testHtml('allows form elements',
175 validator,
176 '<form method="post" action="/foo"></form>');
177
178 testHtml('disallows script navigation',
179 validator,
180 '<a href="javascript:foo = 1">foo</a>',
181 '<a>foo</a>');
182
183 testHtml('disallows cross-site navigation',
184 validator,
185 '<a href="http://example.com">example.com</a>',
186 '<a>example.com</a>');
187
188 testHtml('blocks other elements',
189 validator,
190 '<a href="#foo"><b>foo</b></a>',
191 '<a href="#foo"></a>');
192
193 testHtml('blocks tag extension',
194 validator,
195 '<a is="x-foo"></a>',
196 '');
197 });
198
199 group('allowImages', () {
200 var validator = new NodeValidatorBuilder()..allowImages();
201
202 testHtml('allows images',
203 validator,
204 '<img src="/foo.jpg" alt="something" width="100" height="100"/>');
205
206 testHtml('blocks onerror',
207 validator,
208 '<img src="/foo.jpg" onerror="something"/>',
209 '<img src="/foo.jpg"/>');
210
211 testHtml('enforces same-origin',
212 validator,
213 '<img src="http://example.com/foo.jpg"/>',
214 '<img/>');
215 });
216
217 group('allowCustomElement', () {
218 var validator = new NodeValidatorBuilder()
219 ..allowCustomElement(
220 'x-foo',
221 attributes: ['bar'],
222 uriAttributes: ['baz'])
223 ..allowHtml5();
224
225 testHtml('allows custom elements',
226 validator,
227 '<x-foo bar="something" baz="/foo.jpg"></x-foo>');
228
229
230 testHtml('validates custom tag URIs',
231 validator,
232 '<x-foo baz="http://example.com/foo.jpg"></x-foo>',
233 '<x-foo></x-foo>');
234
235 testHtml('blocks type extensions',
236 validator,
237 '<div is="x-foo"></div>',
238 '');
239
240 testHtml('blocks tags on non-matching elements',
241 validator,
242 '<div bar="foo"></div>',
243 '<div></div>');
244 });
245
246 group('allowTagExtension', () {
247 var validator = new NodeValidatorBuilder()
248 ..allowTagExtension(
249 'x-foo',
250 'div',
251 attributes: ['bar'],
252 uriAttributes: ['baz'])
253 ..allowHtml5();
254
255 testHtml('allows tag extensions',
256 validator,
257 '<div is="x-foo" bar="something" baz="/foo.jpg"></div>');
258
259 testHtml('blocks custom elements',
260 validator,
261 '<x-foo></x-foo>',
262 '');
263
264 testHtml('validates tag extension URIs',
265 validator,
266 '<div is="x-foo" baz="http://example.com/foo.jpg"></div>',
267 '<div is="x-foo"></div>');
268
269 testHtml('blocks tags on non-matching elements',
270 validator,
271 '<div bar="foo"></div>',
272 '<div></div>');
273
274 testHtml('blocks non-matching tags',
275 validator,
276 '<span is="x-foo">something</span>',
277 '');
278
279 validator = new NodeValidatorBuilder()
280 ..allowTagExtension(
281 'x-foo',
282 'div',
283 attributes: ['bar'],
284 uriAttributes: ['baz'])
285 ..allowTagExtension(
286 'x-else',
287 'div');
288
289 testHtml('blocks tags on non-matching custom elements',
290 validator,
291 '<div bar="foo" is="x-else"></div>',
292 '<div is="x-else"></div>');
293 });
294
295 group('allowTemplating', () {
296 var validator = new NodeValidatorBuilder()
297 ..allowTemplating()
298 ..allowHtml5();
299
300 testHtml('allows templates',
301 validator,
302 '<template bind="{{a}}"></template>');
303
304 testHtml('allows template attributes',
305 validator,
306 '<template bind="{{a}}" ref="foo" repeat="{{}}" if="{{}}" syntax="foo" ></template>');
307
308 testHtml('allows template attribute',
309 validator,
310 '<div template repeat="{{}}"></div>');
311
312 testHtml('blocks illegal template attribute',
313 validator,
314 '<div template="foo" repeat="{{}}"></div>',
315 '<div></div>');
316 });
317
318 group('allowSvg', () {
319 var validator = new NodeValidatorBuilder()..allowSvg();
320
321 testHtml('allows basic SVG',
322 validator,
323 '<svg xmlns="http://www.w3.org/2000/svg'
324 'xmlns:xlink="http://www.w3.org/1999/xlink">'
325 '<image xlink:href="foo" data-foo="bar"/>'
326 '</svg>');
327
328 testHtml('blocks script elements',
329 validator,
330 '<svg xmlns="http://www.w3.org/2000/svg>'
331 '<script></script>'
332 '</svg>',
333 '<svg xmlns="http://www.w3.org/2000/svg></svg>');
334
335 testHtml('blocks script handlers',
336 validator,
337 '<svg xmlns="http://www.w3.org/2000/svg'
338 'xmlns:xlink="http://www.w3.org/1999/xlink">'
339 '<image xlink:href="foo" onerror="something"/>'
340 '</svg>',
341 '<svg xmlns="http://www.w3.org/2000/svg'
342 'xmlns:xlink="http://www.w3.org/1999/xlink">'
343 '<image xlink:href="foo"/>'
344 '</svg>');
345
346 testHtml('blocks foreignObject content',
347 validator,
348 '<svg xmlns="http://www.w3.org/2000/svg>'
349 '<foreignobject width="100" height="150">'
350 '<body xmlns="http://www.w3.org/1999/xhtml">'
351 '<div>Some content</div>'
352 '</body>'
353 '</foreignobject>'
354 '</svg>',
355 '<svg xmlns="http://www.w3.org/2000/svg>'
356 '<foreignobject width="100" height="150"></foreignobject>'
357 '</svg>');
358 });
359 });
360
361 group('svg', () {
362 test('parsing', () {
363 var svgText =
364 '<svg xmlns="http://www.w3.org/2000/svg'
365 'xmlns:xlink="http://www.w3.org/1999/xlink">'
366 '<image xlink:href="foo" data-foo="bar"/>'
367 '</svg>';
368
369 var fragment = new DocumentFragment.svg(svgText);
370 var element = fragment.nodes.first;
371 expect(element is svg.SvgSvgElement, isTrue);
372 expect(element.children[0] is svg.ImageElement, isTrue);
373 });
374 });
375 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698