Chromium Code Reviews| Index: tests/html/safe_dom_test.dart |
| diff --git a/tests/html/safe_dom_test.dart b/tests/html/safe_dom_test.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7e431100323adced6dc7e65d6323d040f962e518 |
| --- /dev/null |
| +++ b/tests/html/safe_dom_test.dart |
| @@ -0,0 +1,98 @@ |
| +library safe_dom_test; |
| + |
| +import 'dart:async'; |
| +import 'dart:html'; |
| +import '../../pkg/unittest/lib/unittest.dart'; |
| +import '../../pkg/unittest/lib/html_config.dart'; |
| + |
| +main() { |
| + useHtmlConfiguration(); |
| + |
| + // Checks to see if any illegal properties were set via script. |
| + var checkerScript = ''' |
| + window.addEventListener('message', function(e) { |
| + if (e.data == 'check_unsafe') { |
| + if (window.unsafe_value) { |
| + window.postMessage('unsafe_check_failed', '*'); |
| + } else { |
| + window.postMessage('unsafe_check_passed', '*'); |
| + } |
| + //window.alert('checking!'); |
| + } |
| + }, false); |
| + '''; |
| + |
| + var script = new ScriptElement(); |
| + script.text = checkerScript; |
| + document.body.append(script); |
| + |
| + var unsafeString = |
| + '<img src="_.png" onerror="javascript:window.unsafe_value=1;" crap="1"/>'; |
| + |
| + test('Safe DOM', () { |
| + var fragment = createContextualFragment(unsafeString); |
| + |
| + return isSafe().then((value) { |
|
Jennifer Messerly
2013/05/06 23:28:52
Can you "expect" a future? e.g.
expect(isSafe(),
blois
2013/05/07 00:43:08
Yes! Never used that construct before :)
|
| + expect(value, isTrue, reason: 'Expected unsafe code executed.'); |
|
Jennifer Messerly
2013/05/06 23:28:52
the "reason" here is backwards? we expected the co
blois
2013/05/07 00:43:08
Done.
|
| + }); |
| + |
| + return ensureSafe(); |
|
Jennifer Messerly
2013/05/06 23:28:52
this looks like dead code
blois
2013/05/07 00:43:08
Done.
|
| + }); |
| + |
| + // Make sure that scripts did get executed, so we know our detection works. |
| + test('Unsafe Execution', () { |
| + var div = new DivElement(); |
| + div.innerHtml = unsafeString; |
|
Jennifer Messerly
2013/05/06 23:28:52
this is going to need to change if innerHtml is re
blois
2013/05/07 00:43:08
Yeah, this would just use createContextualFragment
|
| + |
| + return isSafe().then((value) { |
| + expect(value, isFalse, reason: 'Expected unsafe code did not execute.'); |
| + }); |
| + }); |
| + |
| + test('Validity', () { |
| + var fragment = createContextualFragment('<span>content</span>'); |
|
Jennifer Messerly
2013/05/06 23:28:52
it might be interesting to run it through our exis
blois
2013/05/07 00:43:08
Yep, this is primarily to make sure that the parsi
|
| + var div = new DivElement(); |
| + div.append(fragment); |
| + |
| + expect(div.nodes.length, 1); |
| + expect(div.nodes[0] is SpanElement, isTrue); |
| + }); |
| +} |
| + |
| +DocumentFragment createContextualFragment(String html, [String contextTag]) { |
| + var doc = document.implementation.createHtmlDocument(''); |
| + |
| + var contextElement; |
| + if (contextTag != null) { |
| + contextElement = doc.$dom_createElement(contextTag); |
| + } else { |
| + contextElement = doc.body; |
| + } |
| + |
| + if (Range.supportsCreateContextualFragment) { |
| + var range = doc.$dom_createRange(); |
| + range.selectNode(contextElement); |
| + return range.createContextualFragment(html); |
| + } else { |
| + contextElement.innerHtml = html; |
| + var fragment = new DocumentFragment();; |
| + while (contextElement.$dom_firstChild != null) { |
| + fragment.append(contextElement.$dom_firstChild); |
| + } |
| + return fragment; |
| + } |
| +} |
| + |
| +// Delay to wait for the image load to fail. |
| +const Duration imageLoadDelay = const Duration(seconds: .5); |
| + |
| +Future<bool> isSafe() { |
| + return new Future.delayed(imageLoadDelay).then((_) { |
| + window.postMessage('check_unsafe', '*'); |
| + }).then((_) { |
| + return window.onMessage.where( |
| + (e) => e.data.startsWith('unsafe_check')).first; |
| + }).then((e) { |
| + return e.data == 'unsafe_check_passed'; |
| + }); |
| +} |