Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/html/trustedresourceurl.js
2868 views
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
21
goog.provide('goog.html.TrustedResourceUrl');
22
23
goog.require('goog.asserts');
24
goog.require('goog.i18n.bidi.Dir');
25
goog.require('goog.i18n.bidi.DirectionalString');
26
goog.require('goog.string.Const');
27
goog.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
*/
55
goog.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 {!Object}
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
*/
79
goog.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
*/
104
goog.html.TrustedResourceUrl.prototype.getTypedStringValue = function() {
105
return this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_;
106
};
107
108
109
/**
110
* @override
111
* @const
112
*/
113
goog.html.TrustedResourceUrl.prototype.implementsGoogI18nBidiDirectionalString =
114
true;
115
116
117
/**
118
* Returns this URLs directionality, which is always {@code LTR}.
119
* @override
120
*/
121
goog.html.TrustedResourceUrl.prototype.getDirection = function() {
122
return goog.i18n.bidi.Dir.LTR;
123
};
124
125
126
if (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
*/
154
goog.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 + '\' of type ' + goog.typeOf(trustedResourceUrl));
176
return 'type_error:TrustedResourceUrl';
177
}
178
};
179
180
181
/**
182
* Creates a TrustedResourceUrl from a format string and arguments.
183
*
184
* The arguments for interpolation into the format string map labels to values.
185
* Values of type `goog.string.Const` are interpolated without modifcation.
186
* Values of other types are cast to string and encoded with
187
* encodeURIComponent.
188
*
189
* `%{<label>}` markers are used in the format string to indicate locations
190
* to be interpolated with the valued mapped to the given label. `<label>`
191
* must contain only alphanumeric and `_` characters.
192
*
193
* The format string must start with one of the following:
194
* - `https://<origin>/`
195
* - `//<origin>/`
196
* - `/<pathStart>`
197
* - `about:blank`
198
*
199
* `<origin>` must contain only alphanumeric or any of the following: `-.:[]`.
200
* `<pathStart>` is any character except `/` and `\`.
201
*
202
* Example usage:
203
*
204
* var url = goog.html.TrustedResourceUrl.format(goog.string.Const.from(
205
* 'https://www.google.com/search?q=%{query}), {'query': searchTerm});
206
*
207
* var url = goog.html.TrustedResourceUrl.format(goog.string.Const.from(
208
* '//www.youtube.com/v/%{videoId}?hl=en&fs=1%{autoplay}'), {
209
* 'videoId': videoId,
210
* 'autoplay': opt_autoplay ?
211
* goog.string.Const.EMPTY : goog.string.Const.from('autoplay=1')
212
* });
213
*
214
* While this function can be used to create a TrustedResourceUrl from only
215
* constants, fromConstant() and fromConstants() are generally preferable for
216
* that purpose.
217
*
218
* @param {!goog.string.Const} format The format string.
219
* @param {!Object<string, (string|number|!goog.string.Const)>} args Mapping
220
* of labels to values to be interpolated into the format string.
221
* goog.string.Const values are interpolated without encoding.
222
* @return {!goog.html.TrustedResourceUrl}
223
* @throws {!Error} On an invalid format string or if a label used in the
224
* the format string is not present in args.
225
*
226
*/
227
goog.html.TrustedResourceUrl.format = function(format, args) {
228
var formatStr = goog.string.Const.unwrap(format);
229
if (!goog.html.TrustedResourceUrl.BASE_URL_.test(formatStr)) {
230
throw new Error('Invalid TrustedResourceUrl format: ' + formatStr);
231
}
232
var result = formatStr.replace(
233
goog.html.TrustedResourceUrl.FORMAT_MARKER_, function(match, id) {
234
if (!Object.prototype.hasOwnProperty.call(args, id)) {
235
throw new Error(
236
'Found marker, "' + id + '", in format string, "' + formatStr +
237
'", but no valid label mapping found ' +
238
'in args: ' + JSON.stringify(args));
239
}
240
var arg = args[id];
241
if (arg instanceof goog.string.Const) {
242
return goog.string.Const.unwrap(arg);
243
} else {
244
return encodeURIComponent(String(arg));
245
}
246
});
247
return goog.html.TrustedResourceUrl
248
.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(result);
249
};
250
251
252
/**
253
* @private @const {!RegExp}
254
*/
255
goog.html.TrustedResourceUrl.FORMAT_MARKER_ = /%{(\w+)}/g;
256
257
258
/**
259
* The URL must be absolute, scheme-relative or path-absolute. So it must
260
* start with:
261
* - https:// followed by allowed origin characters.
262
* - // followed by allowed origin characters.
263
* - / not followed by / or \. There will only be an absolute path.
264
*
265
* Based on
266
* https://url.spec.whatwg.org/commit-snapshots/56b74ce7cca8883eab62e9a12666e2fac665d03d/#url-parsing
267
* an initial / which is not followed by another / or \ will end up in the "path
268
* state" and from there it can only go to "fragment state" and "query state".
269
*
270
* We don't enforce a well-formed domain name. So '.' or '1.2' are valid.
271
* That's ok because the origin comes from a compile-time constant.
272
*
273
* A regular expression is used instead of goog.uri for several reasons:
274
* - Strictness. E.g. we don't want any userinfo component and we don't
275
* want '/./, nor \' in the first path component.
276
* - Small trusted base. goog.uri is generic and might need to change,
277
* reasoning about all the ways it can parse a URL now and in the future
278
* is error-prone.
279
* - Code size. We expect many calls to .format(), many of which might
280
* not be using goog.uri.
281
* - Simplicity. Using goog.uri would likely not result in simpler nor shorter
282
* code.
283
* @private @const {!RegExp}
284
*/
285
goog.html.TrustedResourceUrl.BASE_URL_ =
286
/^(?:https:)?\/\/[0-9a-z.:[\]-]+\/|^\/[^\/\\]|^about:blank(#|$)/i;
287
288
289
/**
290
* Creates a TrustedResourceUrl object from a compile-time constant string.
291
*
292
* Compile-time constant strings are inherently program-controlled and hence
293
* trusted.
294
*
295
* @param {!goog.string.Const} url A compile-time-constant string from which to
296
* create a TrustedResourceUrl.
297
* @return {!goog.html.TrustedResourceUrl} A TrustedResourceUrl object
298
* initialized to {@code url}.
299
*/
300
goog.html.TrustedResourceUrl.fromConstant = function(url) {
301
return goog.html.TrustedResourceUrl
302
.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(
303
goog.string.Const.unwrap(url));
304
};
305
306
307
/**
308
* Creates a TrustedResourceUrl object from a compile-time constant strings.
309
*
310
* Compile-time constant strings are inherently program-controlled and hence
311
* trusted.
312
*
313
* @param {!Array<!goog.string.Const>} parts Compile-time-constant strings from
314
* which to create a TrustedResourceUrl.
315
* @return {!goog.html.TrustedResourceUrl} A TrustedResourceUrl object
316
* initialized to concatenation of {@code parts}.
317
*/
318
goog.html.TrustedResourceUrl.fromConstants = function(parts) {
319
var unwrapped = '';
320
for (var i = 0; i < parts.length; i++) {
321
unwrapped += goog.string.Const.unwrap(parts[i]);
322
}
323
return goog.html.TrustedResourceUrl
324
.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(unwrapped);
325
};
326
327
328
/**
329
* Type marker for the TrustedResourceUrl type, used to implement additional
330
* run-time type checking.
331
* @const {!Object}
332
* @private
333
*/
334
goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
335
336
337
/**
338
* Package-internal utility method to create TrustedResourceUrl instances.
339
*
340
* @param {string} url The string to initialize the TrustedResourceUrl object
341
* with.
342
* @return {!goog.html.TrustedResourceUrl} The initialized TrustedResourceUrl
343
* object.
344
* @package
345
*/
346
goog.html.TrustedResourceUrl
347
.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse = function(url) {
348
var trustedResourceUrl = new goog.html.TrustedResourceUrl();
349
trustedResourceUrl.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ =
350
url;
351
return trustedResourceUrl;
352
};
353
354