aboutsummaryrefslogtreecommitdiffstats
path: root/src/ng
diff options
context:
space:
mode:
Diffstat (limited to 'src/ng')
-rw-r--r--src/ng/compile.js12
-rw-r--r--src/ng/directive/ngBind.js4
-rw-r--r--src/ng/directive/ngInclude.js23
-rw-r--r--src/ng/interpolate.js27
-rw-r--r--src/ng/sce.js959
-rw-r--r--src/ng/urlUtils.js5
6 files changed, 1003 insertions, 27 deletions
diff --git a/src/ng/compile.js b/src/ng/compile.js
index c059af47..82976822 100644
--- a/src/ng/compile.js
+++ b/src/ng/compile.js
@@ -274,9 +274,9 @@ function $CompileProvider($provide) {
this.$get = [
'$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
- '$controller', '$rootScope', '$document', '$$urlUtils',
+ '$controller', '$rootScope', '$document', '$sce', '$$urlUtils',
function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
- $controller, $rootScope, $document, $$urlUtils) {
+ $controller, $rootScope, $document, $sce, $$urlUtils) {
var Attributes = function(element, attr) {
this.$$element = element;
@@ -1095,7 +1095,7 @@ function $CompileProvider($provide) {
$compileNode.html('');
- $http.get(templateUrl, {cache: $templateCache}).
+ $http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
success(function(content) {
var compileNode, tempTemplateAttrs, $template;
@@ -1203,12 +1203,12 @@ function $CompileProvider($provide) {
}
- function isTrustedContext(node, attrNormalizedName) {
+ function getTrustedContext(node, attrNormalizedName) {
// maction[xlink:href] can source SVG. It's not limited to <maction>.
if (attrNormalizedName == "xlinkHref" ||
(nodeName_(node) != "IMG" && (attrNormalizedName == "src" ||
attrNormalizedName == "ngSrc"))) {
- return true;
+ return $sce.RESOURCE_URL;
}
}
@@ -1238,7 +1238,7 @@ function $CompileProvider($provide) {
// we need to interpolate again, in case the attribute value has been updated
// (e.g. by another directive's compile function)
- interpolateFn = $interpolate(attr[name], true, isTrustedContext(node, name));
+ interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name));
// if attribute was updated so that there is no interpolation going on we don't want to
// register any observers
diff --git a/src/ng/directive/ngBind.js b/src/ng/directive/ngBind.js
index f1cf4c70..fc54adcf 100644
--- a/src/ng/directive/ngBind.js
+++ b/src/ng/directive/ngBind.js
@@ -129,10 +129,10 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
* @element ANY
* @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.
*/
-var ngBindHtmlUnsafeDirective = [function() {
+var ngBindHtmlUnsafeDirective = ['$sce', function($sce) {
return function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);
- scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {
+ scope.$watch($sce.parseAsHtml(attr.ngBindHtmlUnsafe), function ngBindHtmlUnsafeWatchAction(value) {
element.html(value || '');
});
};
diff --git a/src/ng/directive/ngInclude.js b/src/ng/directive/ngInclude.js
index adcc46e5..72b5af08 100644
--- a/src/ng/directive/ngInclude.js
+++ b/src/ng/directive/ngInclude.js
@@ -8,9 +8,20 @@
* @description
* Fetches, compiles and includes an external HTML fragment.
*
- * Keep in mind that Same Origin Policy applies to included resources
- * (e.g. ngInclude won't work for cross-domain requests on all browsers and for
- * file:// access on some browsers).
+ * Keep in mind that:
+ *
+ * - by default, the template URL is restricted to the same domain and protocol as the
+ * application document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl} on it. To load templates from other domains and/or protocols,
+ * you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
+ * {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value. Refer Angular's {@link
+ * ng.$sce Strict Contextual Escaping}.
+ * - in addition, the browser's
+ * {@link https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest
+ * Same Origin Policy} and {@link http://www.w3.org/TR/cors/ Cross-Origin Resource Sharing
+ * (CORS)} policy apply that may further restrict whether the template is successfully loaded.
+ * (e.g. ngInclude won't work for cross-domain requests on all browsers and for `file://`
+ * access on some browsers)
*
* Additionally, you can also provide animations via the ngAnimate attribute to animate the **enter**
* and **leave** effects.
@@ -132,8 +143,8 @@
* @description
* Emitted every time the ngInclude content is reloaded.
*/
-var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile', '$animator',
- function($http, $templateCache, $anchorScroll, $compile, $animator) {
+var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile', '$animator', '$sce',
+ function($http, $templateCache, $anchorScroll, $compile, $animator, $sce) {
return {
restrict: 'ECA',
terminal: true,
@@ -155,7 +166,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
animate.leave(element.contents(), element);
};
- scope.$watch(srcExp, function ngIncludeWatchAction(src) {
+ scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {
var thisChangeId = ++changeCounter;
if (src) {
diff --git a/src/ng/interpolate.js b/src/ng/interpolate.js
index 8e94fe24..ade5ce69 100644
--- a/src/ng/interpolate.js
+++ b/src/ng/interpolate.js
@@ -54,7 +54,7 @@ function $InterpolateProvider() {
};
- this.$get = ['$parse', '$exceptionHandler', function($parse, $exceptionHandler) {
+ this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
var startSymbolLength = startSymbol.length,
endSymbolLength = endSymbol.length;
@@ -64,6 +64,7 @@ function $InterpolateProvider() {
* @function
*
* @requires $parse
+ * @requires $sce
*
* @description
*
@@ -84,12 +85,10 @@ function $InterpolateProvider() {
* @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
* embedded expression in order to return an interpolation function. Strings with no
* embedded expression will return null for the interpolation function.
- * @param {boolean=} isTrustedContext when true, requires that the interpolation string does not
- * contain any concatenations - i.e. the interpolation string is a single expression.
- * Interpolations for *[src] and *[ng-src] (except IMG, since itwhich sanitizes its value)
- * pass true for this parameter. This helps avoid hunting through the template code to
- * figure out of some iframe[src], object[src], etc. was interpolated with a concatenation
- * that ended up introducing a XSS.
+ * @param {string=} trustedContext when provided, the returned function passes the interpolated
+ * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
+ * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
+ * provides Strict Contextual Escaping for details.
* @returns {function(context)} an interpolation function which is used to compute the interpolated
* string. The function has these parameters:
*
@@ -97,7 +96,7 @@ function $InterpolateProvider() {
* against.
*
*/
- function $interpolate(text, mustHaveExpression, isTrustedContext) {
+ function $interpolate(text, mustHaveExpression, trustedContext) {
var startIndex,
endIndex,
index = 0,
@@ -135,10 +134,11 @@ function $InterpolateProvider() {
// is assigned or constructed by some JS code somewhere that is more testable or make it
// obvious that you bound the value to some user controlled value. This helps reduce the load
// when auditing for XSS issues.
- if (isTrustedContext && parts.length > 1) {
+ if (trustedContext && parts.length > 1) {
throw $interpolateMinErr('noconcat',
- "Error while interpolating: {0}\nYou may not use multiple expressions when " +
- "interpolating this expression.", text);
+ "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
+ "interpolations that concatenate multiple expressions when a trusted value is " +
+ "required. See http://docs.angularjs.org/api/ng.$sce", text);
}
if (!mustHaveExpression || hasInterpolation) {
@@ -148,6 +148,11 @@ function $InterpolateProvider() {
for(var i = 0, ii = length, part; i<ii; i++) {
if (typeof (part = parts[i]) == 'function') {
part = part(context);
+ if (trustedContext) {
+ part = $sce.getTrusted(trustedContext, part);
+ } else {
+ part = $sce.valueOf(part);
+ }
if (part == null || part == undefined) {
part = '';
} else if (typeof part != 'string') {
diff --git a/src/ng/sce.js b/src/ng/sce.js
new file mode 100644
index 00000000..ab3d2208
--- /dev/null
+++ b/src/ng/sce.js
@@ -0,0 +1,959 @@
+'use strict';
+
+var $sceMinErr = minErr('$sce');
+
+var SCE_CONTEXTS = {
+ HTML: 'html',
+ CSS: 'css',
+ URL: 'url',
+ // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
+ // url. (e.g. ng-include, script src, templateUrl)
+ RESOURCE_URL: 'resourceUrl',
+ JS: 'js'
+};
+
+
+/**
+ * @ngdoc service
+ * @name ng.$sceDelegate
+ * @function
+ *
+ * @description
+ *
+ * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
+ * Contextual Escaping (SCE)} services to AngularJS.
+ *
+ * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
+ * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is
+ * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
+ * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
+ * work because `$sce` delegates to `$sceDelegate` for these operations.
+ *
+ * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
+ *
+ * The default instance of `$sceDelegate` should work out of the box with little pain. While you
+ * can override it completely to change the behavior of `$sce`, the common case would
+ * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
+ * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as
+ * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist
+ * $sceDelegateProvider.resourceUrlWhitelist} and {@link
+ * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
+ */
+
+/**
+ * @ngdoc object
+ * @name ng.$sceDelegateProvider
+ * @description
+ *
+ * The $sceDelegateProvider provider allows developers to configure the {@link ng.$sceDelegate
+ * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure
+ * that URLs used for sourcing Angular templates are safe. Refer {@link
+ * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
+ * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
+ *
+ * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
+ */
+
+function $SceDelegateProvider() {
+ this.SCE_CONTEXTS = SCE_CONTEXTS;
+
+ // Resource URLs can also be trusted by policy.
+ var resourceUrlWhitelist = ['self'],
+ resourceUrlBlacklist = [];
+
+ /**
+ * @ngdoc function
+ * @name ng.sceDelegateProvider#resourceUrlWhitelist
+ * @methodOf ng.$sceDelegateProvider
+ * @function
+ *
+ * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
+ * provided. This must be an array.
+ *
+ * Each element of this array must either be a regex or the special string `'self'`.
+ *
+ * When a regex is used, it is matched against the normalized / absolute URL of the resource
+ * being tested.
+ *
+ * The **special string** `'self'` can be used to match against all URLs of the same domain as the
+ * application document with the same protocol (allows sourcing https resources from http documents.)
+ *
+ * Please note that **an empty whitelist array will block all URLs**!
+ *
+ * @return {Array} the currently set whitelist array.
+ *
+ * The **default value** when no whitelist has been explicitly set is `['self']`.
+ *
+ * @description
+ * Sets/Gets the whitelist of trusted resource URLs.
+ */
+ this.resourceUrlWhitelist = function (value) {
+ if (arguments.length) {
+ resourceUrlWhitelist = value;
+ }
+ return resourceUrlWhitelist;
+ };
+
+ /**
+ * @ngdoc function
+ * @name ng.sceDelegateProvider#resourceUrlBlacklist
+ * @methodOf ng.$sceDelegateProvider
+ * @function
+ *
+ * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
+ * provided. This must be an array.
+ *
+ * Each element of this array must either be a regex or the special string `'self'` (see
+ * `resourceUrlWhitelist` for meaning - it's only really useful there.)
+ *
+ * When a regex is used, it is matched against the normalized / absolute URL of the resource
+ * being tested.
+ *
+ * The typical usage for the blacklist is to **block [open redirects](http://cwe.mitre.org/data/definitions/601.html)**
+ * served by your domain as these would otherwise be trusted but actually return content from the redirected
+ * domain.
+ *
+ * Finally, **the blacklist overrides the whitelist** and has the final say.
+ *
+ * @return {Array} the currently set blacklist array.
+ *
+ * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there is
+ * no blacklist.)
+ *
+ * @description
+ * Sets/Gets the blacklist of trusted resource URLs.
+ */
+
+ this.resourceUrlBlacklist = function (value) {
+ if (arguments.length) {
+ resourceUrlBlacklist = value;
+ }
+ return resourceUrlBlacklist;
+ };
+
+ // Helper functions for matching resource urls by policy.
+ function isCompatibleProtocol(documentProtocol, resourceProtocol) {
+ return ((documentProtocol === resourceProtocol) ||
+ (documentProtocol === "http:" && resourceProtocol === "https:"));
+ }
+
+ this.$get = ['$log', '$document', '$$urlUtils', function(
+ $log, $document, $$urlUtils) {
+
+ function matchUrl(matcher, parsedUrl) {
+ if (matcher === 'self') {
+ return $$urlUtils.isSameOrigin(parsedUrl);
+ } else {
+ return !!parsedUrl.href.match(matcher);
+ }
+ }
+
+ function isResourceUrlAllowedByPolicy(url) {
+ var parsedUrl = $$urlUtils.resolve(url.toString(), true);
+ var i, n, allowed = false;
+ // Ensure that at least one item from the whitelist allows this url.
+ for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
+ if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
+ allowed = true;
+ break;
+ }
+ }
+ if (allowed) {
+ // Ensure that no item from the blacklist blocked this url.
+ for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
+ if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
+ allowed = false;
+ break;
+ }
+ }
+ }
+ return allowed;
+ }
+
+ function generateHolderType(base) {
+ var holderType = function TrustedValueHolderType(trustedValue) {
+ this.$$unwrapTrustedValue = function() {
+ return trustedValue;
+ };
+ };
+ if (base) {
+ holderType.prototype = new base();
+ }
+ holderType.prototype.valueOf = function sceValueOf() {
+ return this.$$unwrapTrustedValue();
+ }
+ holderType.prototype.toString = function sceToString() {
+ return this.$$unwrapTrustedValue().toString();
+ }
+ return holderType;
+ }
+
+ var trustedValueHolderBase = generateHolderType(),
+ byType = {};
+
+ byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);
+
+ /**
+ * @ngdoc method
+ * @name ng.$sceDelegate#trustAs
+ * @methodOf ng.$sceDelegate
+ *
+ * @description
+ * Returns an object that is trusted by angular for use in specified strict
+ * contextual escaping contexts (such as ng-html-bind-unsafe, ng-include, any src
+ * attribute interpolation, any dom event binding attribute interpolation
+ * such as for onclick, etc.) that uses the provided value.
+ * See {@link ng.$sce $sce} for enabling strict contextual escaping.
+ *
+ * @param {string} type The kind of context in which this value is safe for use. e.g. url,
+ * resourceUrl, html, js and css.
+ * @param {*} value The value that that should be considered trusted/safe.
+ * @returns {*} A value that can be used to stand in for the provided `value` in places
+ * where Angular expects a $sce.trustAs() return value.
+ */
+ function trustAs(type, trustedValue) {
+ var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
+ if (!constructor) {
+ throw $sceMinErr('icontext', 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
+ type, trustedValue);
+ }
+ if (trustedValue === null || trustedValue === undefined || trustedValue === '') {
+ return trustedValue;
+ }
+ // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting
+ // mutable objects, we ensure here that the value passed in is actually a string.
+ if (typeof trustedValue !== 'string') {
+ throw $sceMinErr('itype',
+ 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
+ type);
+ }
+ return new constructor(trustedValue);
+ }
+
+ /**
+ * @ngdoc method
+ * @name ng.$sceDelegate#valueOf
+ * @methodOf ng.$sceDelegate
+ *
+ * @description
+ * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link
+ * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.
+ *
+ * If the passed parameter is not a value that had been returned by {@link
+ * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.
+ *
+ * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}
+ * call or anything else.
+ * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns `value`
+ * unchanged.
+ */
+ function valueOf(maybeTrusted) {
+ if (maybeTrusted instanceof trustedValueHolderBase) {
+ return maybeTrusted.$$unwrapTrustedValue();
+ } else {
+ return maybeTrusted;
+ }
+ }
+
+ /**
+ * @ngdoc method
+ * @name ng.$sceDelegate#getTrusted
+ * @methodOf ng.$sceDelegate
+ *
+ * @description
+ * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and returns the
+ * originally supplied value if the queried context type is a supertype of the created type. If
+ * this condition isn't satisfied, throws an exception.
+ *
+ * @param {string} type The kind of context in which this value is to be used.
+ * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} call.
+ * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
+ */
+ function getTrusted(type, maybeTrusted) {
+ if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {
+ return maybeTrusted;
+ }
+ var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
+ if (constructor && maybeTrusted instanceof constructor) {
+ return maybeTrusted.$$unwrapTrustedValue();
+ }
+ if (type === SCE_CONTEXTS.RESOURCE_URL) {
+ if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
+ return maybeTrusted;
+ } else {
+ throw $sceMinErr('isecrurl',
+ 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}', maybeTrusted.toString());
+ return;
+ }
+ }
+ throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
+ }
+
+ return { trustAs: trustAs,
+ getTrusted: getTrusted,
+ valueOf: valueOf };
+ }];
+}
+
+
+/**
+ * @ngdoc object
+ * @name ng.$sceProvider
+ * @description
+ *
+ * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.
+ * - enable/disable Strict Contextual Escaping (SCE) in a module
+ * - override the default implementation with a custom delegate
+ *
+ * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
+ */
+
+/**
+ * @ngdoc service
+ * @name ng.$sce
+ * @function
+ *
+ * @description
+ *
+ * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.
+ *
+ * # Strict Contextual Escaping
+ *
+ * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
+ * contexts to result in a value that is marked as safe to use for that context One example of such
+ * a context is binding arbitrary html controlled by the user via `ng-bind-html-unsafe`. We refer
+ * to these contexts as privileged or SCE contexts.
+ *
+ * As of version 1.2, Angular ships with SCE enabled by default.
+ *
+ * Note: When enabled (the default), IE8 in quirks mode is not supported. In this mode, IE8 allows
+ * one to execute arbitrary javascript by the use of the expression() syntax. Refer
+ * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
+ * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
+ * to the top of your HTML document.
+ *
+ * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
+ * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
+ *
+ * Here's an example of a binding in a privileged context:
+ *
+ * <pre class="prettyprint">
+ * <input ng-model="userHtml">
+ * <div ng-bind-html-unsafe="{{userHtml}}">
+ * </pre>
+ *
+ * Notice that `ng-bind-html-unsafe` is bound to `{{userHtml}}` controlled by the user. With SCE
+ * disabled, this application allows the user to render arbitrary HTML into the DIV.
+ * In a more realistic example, one may be rendering user comments, blog articles, etc. via
+ * bindings. (HTML is just one example of a context where rendering user controlled input creates
+ * security vulnerabilities.)
+ *
+ * For the case of HTML, you might use a library, either on the client side, or on the server side,
+ * to sanitize unsafe HTML before binding to the value and rendering it in the document.
+ *
+ * How would you ensure that every place that used these types of bindings was bound to a value that
+ * was sanitized by your library (or returned as safe for rendering by your server?) How can you
+ * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
+ * properties/fields and forgot to update the binding to the sanitized value?
+ *
+ * To be secure by default, you want to ensure that any such bindings are disallowed unless you can
+ * determine that something explicitly says it's safe to use a value for binding in that
+ * context. You can then audit your code (a simple grep would do) to ensure that this is only done
+ * for those values that you can easily tell are safe - because they were received from your server,
+ * sanitized by your library, etc. You can organize your codebase to help with this - perhaps
+ * allowing only the files in a specific directory to do this. Ensuring that the internal API
+ * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
+ *
+ * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs} (and shorthand
+ * methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to obtain values that will be
+ * accepted by SCE / privileged contexts.
+ *
+ *
+ * ## How does it work?
+ *
+ * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
+ * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link
+ * ng.$sce#parse $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
+ * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
+ *
+ * As an example, {@link ng.directive:ngBindHtmlUnsafe ngBindHtmlUnsafe} uses {@link
+ * ng.$sce#parseHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
+ * simplified):
+ *
+ * <pre class="prettyprint">
+ * var ngBindHtmlUnsafeDirective = ['$sce', function($sce) {
+ * return function(scope, element, attr) {
+ * scope.$watch($sce.parseAsHtml(attr.ngBindHtmlUnsafe), function(value) {
+ * element.html(value || '');
+ * });
+ * };
+ * }];
+ * </pre>
+ *
+ * ## Impact on loading templates
+ *
+ * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
+ * `templateUrl`'s specified by {@link guide/directive directives}.
+ *
+ * By default, Angular only loads templates from the same domain and protocol as the application
+ * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or
+ * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
+ * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
+ *
+ * *Please note*:
+ * The browser's
+ * {@link https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest
+ * Same Origin Policy} and {@link http://www.w3.org/TR/cors/ Cross-Origin Resource Sharing (CORS)}
+ * policy apply in addition to this and may further restrict whether the template is successfully
+ * loaded. This means that without the right CORS policy, loading templates from a different domain
+ * won't work on all browsers. Also, loading templates from `file://` URL does not work on some
+ * browsers.
+ *
+ * ## This feels like too much overhead for the developer?
+ *
+ * It's important to remember that SCE only applies to interpolation expressions.
+ *
+ * If your expressions are constant literals, they're automatically trusted and you don't need to
+ * call `$sce.trustAs` on them. (e.g.
+ * `<div ng-html-bind-unsafe="'<b>implicitly trusted</b>'"></div>`) just works.
+ *
+ * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
+ * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.
+ *
+ * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
+ * templates in `ng-include` from your application's domain without having to even know about SCE.
+ * It blocks loading templates from other domains or loading templates over http from an https
+ * served document. You can change these by setting your own custom {@link
+ * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link
+ * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.
+ *
+ * This significantly reduces the overhead. It is far easier to pay the small overhead and have an
+ * application that's secure and can be audited to verify that with much more ease than bolting
+ * security onto an application later.
+ *
+ * ## What trusted context types are supported?<a name="contexts"></a>
+ *
+ * | Context | Notes |
+ * |=====================|================|
+ * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtmlUnsafe ngBindHtmlUnsafe} directive uses this context for bindings. |
+ * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
+ * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't consititute an SCE context. |
+ * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contens are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
+ * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
+ *
+ * ## Show me an example.
+ *
+ *
+ *
+ * @example
+ <example module="mySceApp">
+ <file name="index.html">
+ <div ng-controller="myAppController as myCtrl">
+ <button ng-click="myCtrl.fetchUserComments()" id="fetchBtn">Fetch Comments</button>
+ <div ng-show="myCtrl.errorMsg">Error: {{myCtrl.errorMsg}}</div>
+ <div ng-repeat="userComment in myCtrl.userComments">
+ <hr>
+ <b>{{userComment.name}}</b>:
+ <span ng-bind-html-unsafe="userComment.htmlComment" class="htmlComment"></span>
+ </div>
+ <div ng-bind-html-unsafe="myCtrl.someHtml" id="someHtml"></div>
+ </div>
+ </file>
+
+ <file name="script.js">
+ // These types of functions would be in the data access layer of your application code.
+ function fetchUserCommentsFromServer($http, $q, $templateCache, $sce) {
+ var deferred = $q.defer();
+ $http({method: "GET", url: "test_data.json", cache: $templateCache}).
+ success(function(userComments, status) {
+ // The comments coming from the server have been sanitized by the server and can be
+ // trusted.
+ angular.forEach(userComments, function(userComment) {
+ userComment.htmlComment = $sce.trustAsHtml(userComment.htmlComment);
+ });
+ deferred.resolve(userComments);
+ }).
+ error(function (data, status) {
+ deferred.reject("HTTP status code " + status + ": " + data);
+ });
+ return deferred.promise;
+ };
+
+ var mySceApp = angular.module('mySceApp', []);
+
+ mySceApp.controller("myAppController", function myAppController($injector) {
+ var self = this;
+
+ self.someHtml = "This might have been any binding including an input element " +
+ "controlled by the user.";
+
+ self.fetchUserComments = function() {
+ $injector.invoke(fetchUserCommentsFromServer).then(
+ function onSuccess(userComments) {
+ self.errorMsg = null;
+ self.userComments = userComments;
+ },
+ function onFailure(errorMsg) {
+ self.errorMsg = errorMsg;
+ });
+ }
+ });
+ </file>
+
+ <file name="test_data.json">
+ [
+ { "name": "Alice",
+ "htmlComment": "Is <i>anyone</i> reading this?"
+ },
+ { "name": "Bob",
+ "htmlComment": "<i>Yes!</i> Am I the only other one?"
+ }
+ ]
+ </file>
+
+ <file name="scenario.js">
+ describe('SCE doc demo', function() {
+ it('should bind trusted values', function() {
+ element('#fetchBtn').click();
+ expect(element('.htmlComment').html()).toBe('Is <i>anyone</i> reading this?');
+ });
+ it('should NOT bind arbitrary values', function() {
+ expect(element('#someHtml').html()).toBe('');
+ });
+ });
+ </file>
+ </example>
+ *
+ *
+ *
+ * ## Can I disable SCE completely?
+ *
+ * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits
+ * for little coding overhead. It will be much harder to take an SCE disabled application and
+ * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE
+ * for cases where you have a lot of existing code that was written before SCE was introduced and
+ * you're migrating them a module at a time.
+ *
+ * That said, here's how you can completely disable SCE:
+ *
+ * <pre class="prettyprint">
+ * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
+ * // Completely disable SCE. For demonstration purposes only!
+ * // Do not use in new projects.
+ * $sceProvider.enabled(false);
+ * });
+ * </pre>
+ *
+ */
+
+function $SceProvider() {
+ var enabled = true;
+
+ /**
+ * @ngdoc function
+ * @name ng.sceProvider#enabled
+ * @methodOf ng.$sceProvider
+ * @function
+ *
+ * @param {boolean=} value If provided, then enables/disables SCE.
+ * @return {boolean} true if SCE is enabled, false otherwise.
+ *
+ * @description
+ * Enables/disables SCE and returns the current value.
+ */
+ this.enabled = function (value) {
+ if (arguments.length) {
+ enabled = !!value;
+ }
+ return enabled;
+ };
+
+
+ /* Design notes on the default implementation for SCE.
+ *
+ * The API contract for the SCE delegate
+ * -------------------------------------
+ * The SCE delegate object must provide the following 3 methods:
+ *
+ * - trustAs(contextEnum, value)
+ * This method is used to tell the SCE service that the provided value is OK to use in the
+ * contexts specified by contextEnum. It must return an object that will be accepted by
+ * getTrusted() for a compatible contextEnum and return this value.
+ *
+ * - valueOf(value)
+ * For values that were not produced by trustAs(), return them as is. For values that were
+ * produced by trustAs(), return the corresponding input value to trustAs. Basically, if
+ * trustAs is wrapping the given values into some type, this operation unwraps it when given
+ * such a value.
+ *
+ * - getTrusted(contextEnum, value)
+ * This function should return the a value that is safe to use in the context specified by
+ * contextEnum or throw and exception otherwise.
+ *
+ * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be opaque
+ * or wrapped in some holder object. That happens to be an implementation detail. For instance,
+ * an implementation could maintain a registry of all trusted objects by context. In such a case,
+ * trustAs() would return the same object that was passed in. getTrusted() would return the same
+ * object passed in if it was found in the registry under a compatible context or throw an
+ * exception otherwise. An implementation might only wrap values some of the time based on
+ * some criteria. getTrusted() might return a value and not throw an exception for special
+ * constants or objects even if not wrapped. All such implementations fulfill this contract.
+ *
+ *
+ * A note on the inheritance model for SCE contexts
+ * ------------------------------------------------
+ * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This
+ * is purely an implementation details.
+ *
+ * The contract is simply this:
+ *
+ * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
+ * will also succeed.
+ *
+ * Inheritance happens to capture this in a natural way. In some future, we
+ * may not use inheritance anymore. That is OK because no code outside of
+ * sce.js and sceSpecs.js would need to be aware of this detail.
+ */
+
+ this.$get = ['$parse', '$document', '$sceDelegate', function(
+ $parse, $document, $sceDelegate) {
+ // Prereq: Ensure that we're not running in IE8 quirks mode. In that mode, IE allows
+ // the "expression(javascript expression)" syntax which is insecure.
+ if (enabled && msie) {
+ var documentMode = $document[0].documentMode;
+ if (documentMode !== undefined && documentMode < 8) {
+ throw $sceMinErr('iequirks',
+ 'Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks ' +
+ 'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' +
+ 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');
+ }
+ }
+
+ var sce = copy(SCE_CONTEXTS);
+
+ /**
+ * @ngdoc function
+ * @name ng.sce#isEnabled
+ * @methodOf ng.$sce
+ * @function
+ *
+ * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
+ * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
+ *
+ * @description
+ * Returns a boolean indicating if SCE is enabled.
+ */
+ sce.isEnabled = function () {
+ return enabled;
+ };
+ sce.trustAs = $sceDelegate.trustAs;
+ sce.getTrusted = $sceDelegate.getTrusted;
+ sce.valueOf = $sceDelegate.valueOf;
+
+ if (!enabled) {
+ sce.trustAs = sce.getTrusted = function(type, value) { return value; },
+ sce.valueOf = identity
+ }
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#parse
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Converts Angular {@link guide/expression expression} into a function. This is like {@link
+ * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it
+ * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
+ * *result*)}
+ *
+ * @param {string} type The kind of SCE context in which this result will be used.
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+ sce.parseAs = function sceParseAs(type, expr) {
+ var parsed = $parse(expr);
+ if (parsed.literal && parsed.constant) {
+ return parsed;
+ } else {
+ return function sceParseAsTrusted(self, locals) {
+ return sce.getTrusted(type, parsed(self, locals));
+ }
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#trustAs
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such, returns an object
+ * that is trusted by angular for use in specified strict contextual escaping contexts (such as
+ * ng-html-bind-unsafe, ng-include, any src attribute interpolation, any dom event binding
+ * attribute interpolation such as for onclick, etc.) that uses the provided value. See *
+ * {@link ng.$sce $sce} for enabling strict contextual escaping.
+ *
+ * @param {string} type The kind of context in which this value is safe for use. e.g. url,
+ * resource_url, html, js and css.
+ * @param {*} value The value that that should be considered trusted/safe.
+ * @returns {*} A value that can be used to stand in for the provided `value` in places
+ * where Angular expects a $sce.trustAs() return value.
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#trustAsHtml
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsHtml(value)` → {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
+ * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#trustAsUrl
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsUrl(value)` → {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
+ * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#trustAsResourceUrl
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsResourceUrl(value)` → {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the return
+ * value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#trustAsJs
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsJs(value)` → {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
+ * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#getTrusted
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such, takes
+ * the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the originally supplied
+ * value if the queried context type is a supertype of the created type. If this condition
+ * isn't satisfied, throws an exception.
+ *
+ * @param {string} type The kind of context in which this value is to be used.
+ * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`} call.
+ * @returns {*} The value the was originally provided to {@link ng.$sce#trustAs `$sce.trustAs`} if
+ * valid in this context. Otherwise, throws an exception.
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#getTrustedHtml
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedHtml(value)` → {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#getTrustedCss
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedCss(value)` → {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#getTrustedUrl
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedUrl(value)` → {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#getTrustedResourceUrl
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedResourceUrl(value)` → {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
+ *
+ * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#getTrustedJs
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedJs(value)` → {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#parseAsHtml
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsHtml(expression string)` → {@link ng.$sce#parse `$sce.parseAs($sce.HTML, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#parseAsCss
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsCss(value)` → {@link ng.$sce#parse `$sce.parseAs($sce.CSS, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#parseAsUrl
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsUrl(value)` → {@link ng.$sce#parse `$sce.parseAs($sce.URL, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#parseAsResourceUrl
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsResourceUrl(value)` → {@link ng.$sce#parse `$sce.parseAs($sce.RESOURCE_URL, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name ng.$sce#parseAsJs
+ * @methodOf ng.$sce
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsJs(value)` → {@link ng.$sce#parse `$sce.parseAs($sce.JS, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ // Shorthand delegations.
+ var parse = sce.parseAs,
+ getTrusted = sce.getTrusted,
+ trustAs = sce.trustAs;
+
+ angular.forEach(SCE_CONTEXTS, function (enumValue, name) {
+ var lName = lowercase(name);
+ sce[camelCase("parse_as_" + lName)] = function (expr) {
+ return parse(enumValue, expr);
+ }
+ sce[camelCase("get_trusted_" + lName)] = function (value) {
+ return getTrusted(enumValue, value);
+ }
+ sce[camelCase("trust_as_" + lName)] = function (value) {
+ return trustAs(enumValue, value);
+ }
+ });
+
+ return sce;
+ }];
+}
diff --git a/src/ng/urlUtils.js b/src/ng/urlUtils.js
index 5402b500..af2d913f 100644
--- a/src/ng/urlUtils.js
+++ b/src/ng/urlUtils.js
@@ -105,11 +105,12 @@ function $$UrlUtilsProvider() {
/**
* Parse a request URL and determine whether this is a same-origin request as the application document.
*
- * @param {string} requestUrl The url of the request.
+ * @param {string|object} requestUrl The url of the request as a string that will be resolved
+ * or a parsed URL object.
* @returns {boolean} Whether the request is for the same origin as the application document.
*/
isSameOrigin: function isSameOrigin(requestUrl) {
- var parsed = resolve(requestUrl, true);
+ var parsed = (typeof requestUrl === 'string') ? resolve(requestUrl, true) : requestUrl;
return (parsed.protocol === originUrl.protocol &&
parsed.host === originUrl.host);
}