|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +function $$UrlUtilsProvider() { |
| 4 | + this.$get = ['$window', '$document', function($window, $document) { |
| 5 | + var urlParsingNode = $document[0].createElement("a"), |
| 6 | + originUrl = resolve($window.location.href, true); |
| 7 | + |
| 8 | + /** |
| 9 | + * @description |
| 10 | + * Normalizes and optionally parses a URL. |
| 11 | + * |
| 12 | + * NOTE: This is a private service. The API is subject to change unpredictably in any commit. |
| 13 | + * |
| 14 | + * Implementation Notes for non-IE browsers |
| 15 | + * ---------------------------------------- |
| 16 | + * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM, |
| 17 | + * results both in the normalizing and parsing of the URL. Normalizing means that a relative |
| 18 | + * URL will be resolved into an absolute URL in the context of the application document. |
| 19 | + * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related |
| 20 | + * properties are all populated to reflect the normalized URL. This approach has wide |
| 21 | + * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See |
| 22 | + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html |
| 23 | + * |
| 24 | + * Implementation Notes for IE |
| 25 | + * --------------------------- |
| 26 | + * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other |
| 27 | + * browsers. However, the parsed components will not be set if the URL assigned did not specify |
| 28 | + * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We |
| 29 | + * work around that by performing the parsing in a 2nd step by taking a previously normalized |
| 30 | + * URL (e.g. by assining to a.href) and assigning it a.href again. This correctly populates the |
| 31 | + * properties such as protocol, hostname, port, etc. |
| 32 | + * |
| 33 | + * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one |
| 34 | + * uses the inner HTML approach to assign the URL as part of an HTML snippet - |
| 35 | + * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL. |
| 36 | + * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception. |
| 37 | + * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that |
| 38 | + * method and IE < 8 is unsupported. |
| 39 | + * |
| 40 | + * References: |
| 41 | + * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement |
| 42 | + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html |
| 43 | + * http://url.spec.whatwg.org/#urlutils |
| 44 | + * https://github.com/angular/angular.js/pull/2902 |
| 45 | + * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ |
| 46 | + * |
| 47 | + * @param {string} url The URL to be parsed. |
| 48 | + * @param {boolean=} parse When true, returns an object for the parsed URL. Otherwise, returns |
| 49 | + * a single string that is the normalized URL. |
| 50 | + * @returns {object|string} When parse is true, returns the normalized URL as a string. |
| 51 | + * Otherwise, returns an object with the following members. |
| 52 | + * |
| 53 | + * | member name | Description | |
| 54 | + * |===============|================| |
| 55 | + * | href | A normalized version of the provided URL if it was not an absolute URL | |
| 56 | + * | protocol | The protocol including the trailing colon | |
| 57 | + * | host | The host and port (if the port is non-default) of the normalizedUrl | |
| 58 | + * |
| 59 | + * These fields from the UrlUtils interface are currently not needed and hence not returned. |
| 60 | + * |
| 61 | + * | member name | Description | |
| 62 | + * |===============|================| |
| 63 | + * | hostname | The host without the port of the normalizedUrl | |
| 64 | + * | pathname | The path following the host in the normalizedUrl | |
| 65 | + * | hash | The URL hash if present | |
| 66 | + * | search | The query string | |
| 67 | + * |
| 68 | + */ |
| 69 | + function resolve(url, parse) { |
| 70 | + var href = url; |
| 71 | + if (msie) { |
| 72 | + // Normalize before parse. Refer Implementation Notes on why this is |
| 73 | + // done in two steps on IE. |
| 74 | + urlParsingNode.setAttribute("href", href); |
| 75 | + href = urlParsingNode.href; |
| 76 | + } |
| 77 | + urlParsingNode.setAttribute('href', href); |
| 78 | + |
| 79 | + if (!parse) { |
| 80 | + return urlParsingNode.href; |
| 81 | + } |
| 82 | + // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils |
| 83 | + return { |
| 84 | + href: urlParsingNode.href, |
| 85 | + protocol: urlParsingNode.protocol, |
| 86 | + host: urlParsingNode.host |
| 87 | + // Currently unused and hence commented out. |
| 88 | + // hostname: urlParsingNode.hostname, |
| 89 | + // port: urlParsingNode.port, |
| 90 | + // pathname: urlParsingNode.pathname, |
| 91 | + // hash: urlParsingNode.hash, |
| 92 | + // search: urlParsingNode.search |
| 93 | + }; |
| 94 | + } |
| 95 | + |
| 96 | + return { |
| 97 | + resolve: resolve, |
| 98 | + /** |
| 99 | + * Parse a request URL and determine whether this is a same-origin request as the application document. |
| 100 | + * |
| 101 | + * @param {string} requestUrl The url of the request. |
| 102 | + * @returns {boolean} Whether the request is for the same origin as the application document. |
| 103 | + */ |
| 104 | + isSameOrigin: function isSameOrigin(requestUrl) { |
| 105 | + var parsed = resolve(requestUrl, true); |
| 106 | + return (parsed.protocol === originUrl.protocol && |
| 107 | + parsed.host === originUrl.host); |
| 108 | + } |
| 109 | + }; |
| 110 | + }]; |
| 111 | +} |
0 commit comments