lib/goog/html/trustedresourceurl.js

1// Copyright 2013 The Closure Library Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS-IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/**
16 * @fileoverview The TrustedResourceUrl type and its builders.
17 *
18 * TODO(xtof): Link to document stating type contract.
19 */
20
21goog.provide('goog.html.TrustedResourceUrl');
22
23goog.require('goog.asserts');
24goog.require('goog.i18n.bidi.Dir');
25goog.require('goog.i18n.bidi.DirectionalString');
26goog.require('goog.string.Const');
27goog.require('goog.string.TypedString');
28
29
30
31/**
32 * A URL which is under application control and from which script, CSS, and
33 * other resources that represent executable code, can be fetched.
34 *
35 * Given that the URL can only be constructed from strings under application
36 * control and is used to load resources, bugs resulting in a malformed URL
37 * should not have a security impact and are likely to be easily detectable
38 * during testing. Given the wide number of non-RFC compliant URLs in use,
39 * stricter validation could prevent some applications from being able to use
40 * this type.
41 *
42 * Instances of this type must be created via the factory method,
43 * ({@code goog.html.TrustedResourceUrl.fromConstant}), and not by invoking its
44 * constructor. The constructor intentionally takes no parameters and the type
45 * is immutable; hence only a default instance corresponding to the empty
46 * string can be obtained via constructor invocation.
47 *
48 * @see goog.html.TrustedResourceUrl#fromConstant
49 * @constructor
50 * @final
51 * @struct
52 * @implements {goog.i18n.bidi.DirectionalString}
53 * @implements {goog.string.TypedString}
54 */
55goog.html.TrustedResourceUrl = function() {
56 /**
57 * The contained value of this TrustedResourceUrl. The field has a purposely
58 * ugly name to make (non-compiled) code that attempts to directly access this
59 * field stand out.
60 * @private {string}
61 */
62 this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ = '';
63
64 /**
65 * A type marker used to implement additional run-time type checking.
66 * @see goog.html.TrustedResourceUrl#unwrap
67 * @const
68 * @private
69 */
70 this.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
71 goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
72};
73
74
75/**
76 * @override
77 * @const
78 */
79goog.html.TrustedResourceUrl.prototype.implementsGoogStringTypedString = true;
80
81
82/**
83 * Returns this TrustedResourceUrl's value as a string.
84 *
85 * IMPORTANT: In code where it is security relevant that an object's type is
86 * indeed {@code TrustedResourceUrl}, use
87 * {@code goog.html.TrustedResourceUrl.unwrap} instead of this method. If in
88 * doubt, assume that it's security relevant. In particular, note that
89 * goog.html functions which return a goog.html type do not guarantee that
90 * the returned instance is of the right type. For example:
91 *
92 * <pre>
93 * var fakeSafeHtml = new String('fake');
94 * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
95 * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
96 * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
97 * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml instanceof
98 * // goog.html.SafeHtml.
99 * </pre>
100 *
101 * @see goog.html.TrustedResourceUrl#unwrap
102 * @override
103 */
104goog.html.TrustedResourceUrl.prototype.getTypedStringValue = function() {
105 return this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_;
106};
107
108
109/**
110 * @override
111 * @const
112 */
113goog.html.TrustedResourceUrl.prototype.implementsGoogI18nBidiDirectionalString =
114 true;
115
116
117/**
118 * Returns this URLs directionality, which is always {@code LTR}.
119 * @override
120 */
121goog.html.TrustedResourceUrl.prototype.getDirection = function() {
122 return goog.i18n.bidi.Dir.LTR;
123};
124
125
126if (goog.DEBUG) {
127 /**
128 * Returns a debug string-representation of this value.
129 *
130 * To obtain the actual string value wrapped in a TrustedResourceUrl, use
131 * {@code goog.html.TrustedResourceUrl.unwrap}.
132 *
133 * @see goog.html.TrustedResourceUrl#unwrap
134 * @override
135 */
136 goog.html.TrustedResourceUrl.prototype.toString = function() {
137 return 'TrustedResourceUrl{' +
138 this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ + '}';
139 };
140}
141
142
143/**
144 * Performs a runtime check that the provided object is indeed a
145 * TrustedResourceUrl object, and returns its value.
146 *
147 * @param {!goog.html.TrustedResourceUrl} trustedResourceUrl The object to
148 * extract from.
149 * @return {string} The trustedResourceUrl object's contained string, unless
150 * the run-time type check fails. In that case, {@code unwrap} returns an
151 * innocuous string, or, if assertions are enabled, throws
152 * {@code goog.asserts.AssertionError}.
153 */
154goog.html.TrustedResourceUrl.unwrap = function(trustedResourceUrl) {
155 // Perform additional Run-time type-checking to ensure that
156 // trustedResourceUrl is indeed an instance of the expected type. This
157 // provides some additional protection against security bugs due to
158 // application code that disables type checks.
159 // Specifically, the following checks are performed:
160 // 1. The object is an instance of the expected type.
161 // 2. The object is not an instance of a subclass.
162 // 3. The object carries a type marker for the expected type. "Faking" an
163 // object requires a reference to the type marker, which has names intended
164 // to stand out in code reviews.
165 if (trustedResourceUrl instanceof goog.html.TrustedResourceUrl &&
166 trustedResourceUrl.constructor === goog.html.TrustedResourceUrl &&
167 trustedResourceUrl
168 .TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
169 goog.html.TrustedResourceUrl
170 .TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
171 return trustedResourceUrl
172 .privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_;
173 } else {
174 goog.asserts.fail('expected object of type TrustedResourceUrl, got \'' +
175 trustedResourceUrl + '\'');
176 return 'type_error:TrustedResourceUrl';
177
178 }
179};
180
181
182/**
183 * Creates a TrustedResourceUrl object from a compile-time constant string.
184 *
185 * Compile-time constant strings are inherently program-controlled and hence
186 * trusted.
187 *
188 * @param {!goog.string.Const} url A compile-time-constant string from which to
189 * create a TrustedResourceUrl.
190 * @return {!goog.html.TrustedResourceUrl} A TrustedResourceUrl object
191 * initialized to {@code url}.
192 */
193goog.html.TrustedResourceUrl.fromConstant = function(url) {
194 return goog.html.TrustedResourceUrl
195 .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(
196 goog.string.Const.unwrap(url));
197};
198
199
200/**
201 * Type marker for the TrustedResourceUrl type, used to implement additional
202 * run-time type checking.
203 * @const {!Object}
204 * @private
205 */
206goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
207
208
209/**
210 * Package-internal utility method to create TrustedResourceUrl instances.
211 *
212 * @param {string} url The string to initialize the TrustedResourceUrl object
213 * with.
214 * @return {!goog.html.TrustedResourceUrl} The initialized TrustedResourceUrl
215 * object.
216 * @package
217 */
218goog.html.TrustedResourceUrl.
219 createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse = function(url) {
220 var trustedResourceUrl = new goog.html.TrustedResourceUrl();
221 trustedResourceUrl.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ =
222 url;
223 return trustedResourceUrl;
224};