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

Side by Side Diff: tools/dom/src/Validators.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 | « tools/dom/src/NodeValidatorBuilder.dart ('k') | tools/dom/src/shared_SVGFactoryProviders.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 part of dart.dom.html;
6
7
8 /**
9 * Interface used to validate that only accepted elements and attributes are
10 * allowed while parsing HTML strings into DOM nodes.
11 *
12 * In general, customization of validation behavior should be done via the
13 * [NodeValidatorBuilder] class to mitigate the chances of incorrectly
14 * implementing validation rules.
15 */
16 abstract class NodeValidator {
17
18 /**
19 * Construct a default NodeValidator which only accepts whitelisted HTML5
20 * elements and attributes.
21 *
22 * If a uriPolicy is not specified then the default uriPolicy will be used.
23 */
24 factory NodeValidator({UriPolicy uriPolicy}) =>
25 new _Html5NodeValidator(uriPolicy: uriPolicy);
26
27 factory NodeValidator.throws(NodeValidator base) =>
28 new _ThrowsNodeValidator(base);
29
30 /**
31 * Returns true if the tagName is an accepted type.
32 */
33 bool allowsElement(Element element);
34
35 /**
36 * Returns true if the attribute is allowed.
37 *
38 * The attributeName parameter will always be in lowercase.
39 *
40 * See [allowsElement] for format of tagName.
41 */
42 bool allowsAttribute(Element element, String attributeName, String value);
43 }
44
45 /**
46 * Performs sanitization of a node tree after construction to ensure that it
47 * does not contain any disallowed elements or attributes.
48 *
49 * In general custom implementations of this class should not be necessary and
50 * all validation customization should be done in custom NodeValidators, but
51 * custom implementations of this class can be created to perform more complex
52 * tree sanitization.
53 */
54 abstract class NodeTreeSanitizer {
55
56 /**
57 * Constructs a default tree sanitizer which will remove all elements and
58 * attributes which are not allowed by the provided validator.
59 */
60 factory NodeTreeSanitizer(NodeValidator validator) =>
61 new _ValidatingTreeSanitizer(validator);
62
63 /**
64 * Called with the root of the tree which is to be sanitized.
65 *
66 * This method needs to walk the entire tree and either remove elements and
67 * attributes which are not recognized as safe or throw an exception which
68 * will mark the entire tree as unsafe.
69 */
70 void sanitizeTree(Node node);
71 }
72
73 /**
74 * Defines the policy for what types of uris are allowed for particular
75 * attribute values.
76 *
77 * This can be used to provide custom rules such as allowing all http:// URIs
78 * for image attributes but only same-origin URIs for anchor tags.
79 */
80 abstract class UriPolicy {
81 /**
82 * Constructs the default UriPolicy which is to only allow Uris to the same
83 * origin as the application was launched from.
84 *
85 * This will block all ftp: mailto: URIs. It will also block accessing
86 * https://example.com if the app is running from http://example.com.
87 */
88 factory UriPolicy() => new _SameOriginUriPolicy();
89
90 /**
91 * Checks if the uri is allowed on the specified attribute.
92 *
93 * The uri provided may or may not be a relative path.
94 */
95 bool allowsUri(String uri);
96 }
97
98 /**
99 * Allows URIs to the same origin as the current application was loaded from
100 * (such as https://example.com:80).
101 */
102 class _SameOriginUriPolicy implements UriPolicy {
103 final AnchorElement _hiddenAnchor = new AnchorElement();
104 final Location _loc = window.location;
105
106 bool allowsUri(String uri) {
107 _hiddenAnchor.href = uri;
108 return _hiddenAnchor.hostname == _loc.hostname &&
109 _hiddenAnchor.port == _loc.port &&
110 _hiddenAnchor.protocol == _loc.protocol;
111 }
112 }
113
114
115 class _ThrowsNodeValidator implements NodeValidator {
116 final NodeValidator validator;
117
118 _ThrowsNodeValidator(this.validator) {}
119
120 bool allowsElement(Element element) {
121 if (!validator.allowsElement(element)) {
122 throw new ArgumentError(element.tagName);
123 }
124 return true;
125 }
126
127 bool allowsAttribute(Element element, String attributeName, String value) {
128 if (!validator.allowsAttribute(element, attributeName, value)) {
129 throw new ArgumentError('${element.tagName}[$attributeName="$value"]');
130 }
131 }
132 }
133
134
135 /**
136 * Standard tree sanitizer which validates a node tree against the provided
137 * validator and removes any nodes or attributes which are not allowed.
138 */
139 class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
140 NodeValidator validator;
141 _ValidatingTreeSanitizer(this.validator) {}
142
143 void sanitizeTree(Node node) {
144 void walk(Node node) {
145 sanitizeNode(node);
146
147 var child = node.lastChild;
148 while (child != null) {
149 // Child may be removed during the walk.
150 var nextChild = child.previousNode;
151 walk(child);
152 child = nextChild;
153 }
154 }
155 walk(node);
156 }
157
158 void sanitizeNode(Node node) {
159 switch (node.nodeType) {
160 case Node.ELEMENT_NODE:
161 Element element = node;
162 var attrs = element.attributes;
163 if (!validator.allowsElement(element)) {
164 element.remove();
165 break;
166 }
167
168 var isAttr = attrs['is'];
169 if (isAttr != null) {
170 if (!validator.allowsAttribute(element, 'is', isAttr)) {
171 element.remove();
172 break;
173 }
174 }
175
176 // TODO(blois): Need to be able to get all attributes, irrespective of
177 // XMLNS.
178 var keys = attrs.keys.toList();
179 for (var i = attrs.length - 1; i >= 0; --i) {
180 var name = keys[i];
181 if (!validator.allowsAttribute(element, name, attrs[name])) {
182 attrs.remove(name);
183 }
184 }
185
186 if (element is TemplateElement) {
187 TemplateElement template = element;
188 sanitizeTree(template.content);
189 }
190 break;
191 case Node.COMMENT_NODE:
192 case Node.DOCUMENT_FRAGMENT_NODE:
193 case Node.TEXT_NODE:
194 case Node.CDATA_SECTION_NODE:
195 break;
196 default:
197 node.remove();
198 }
199 }
200 }
OLDNEW
« no previous file with comments | « tools/dom/src/NodeValidatorBuilder.dart ('k') | tools/dom/src/shared_SVGFactoryProviders.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698