diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Base/URLUtilities.js | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Base/URLUtilities.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/Base/URLUtilities.js | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Base/URLUtilities.js b/Source/WebInspectorUI/UserInterface/Base/URLUtilities.js new file mode 100644 index 000000000..e3935f504 --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/Base/URLUtilities.js @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// FIXME: <https://webkit.org/b/165155> Web Inspector: Use URL constructor to better handle all kinds of URLs + +function removeURLFragment(url) +{ + var hashIndex = url.indexOf("#"); + if (hashIndex >= 0) + return url.substring(0, hashIndex); + return url; +} + +function relativePath(path, basePath) +{ + console.assert(path.charAt(0) === "/"); + console.assert(basePath.charAt(0) === "/"); + + var pathComponents = path.split("/"); + var baseComponents = basePath.replace(/\/$/, "").split("/"); + var finalComponents = []; + + var index = 1; + for (; index < pathComponents.length && index < baseComponents.length; ++index) { + if (pathComponents[index] !== baseComponents[index]) + break; + } + + for (var i = index; i < baseComponents.length; ++i) + finalComponents.push(".."); + + for (var i = index; i < pathComponents.length; ++i) + finalComponents.push(pathComponents[i]); + + return finalComponents.join("/"); +} + +function parseSecurityOrigin(securityOrigin) +{ + securityOrigin = securityOrigin ? securityOrigin.trim() : ""; + + var match = securityOrigin.match(/^([^:]+):\/\/([^\/:]*)(?::([\d]+))?$/i); + if (!match) + return {scheme: null, host: null, port: null}; + + var scheme = match[1].toLowerCase(); + var host = match[2].toLowerCase(); + var port = Number(match[3]) || null; + + return {scheme, host, port}; +} + +function parseDataURL(url) +{ + if (!url.startsWith("data:")) + return null; + + // data:[<media type>][;charset=<character set>][;base64],<data> + let match = url.match(/^data:([^;,]*)?(?:;charset=([^;,]*?))?(;base64)?,(.*)$/); + if (!match) + return null; + + let scheme = "data"; + let mimeType = match[1] || "text/plain"; + let charset = match[2] || "US-ASCII"; + let base64 = !!match[3]; + let data = decodeURIComponent(match[4]); + + return {scheme, mimeType, charset, base64, data}; +} + +function parseURL(url) +{ + url = url ? url.trim() : ""; + + if (url.startsWith("data:")) + return {scheme: "data", host: null, port: null, path: null, queryString: null, fragment: null, lastPathComponent: null}; + + var match = url.match(/^([^\/:]+):\/\/([^\/#:]*)(?::([\d]+))?(?:(\/[^#]*)?(?:#(.*))?)?$/i); + if (!match) + return {scheme: null, host: null, port: null, path: null, queryString: null, fragment: null, lastPathComponent: null}; + + var scheme = match[1].toLowerCase(); + var host = match[2].toLowerCase(); + var port = Number(match[3]) || null; + var wholePath = match[4] || null; + var fragment = match[5] || null; + var path = wholePath; + var queryString = null; + + // Split the path and the query string. + if (wholePath) { + var indexOfQuery = wholePath.indexOf("?"); + if (indexOfQuery !== -1) { + path = wholePath.substring(0, indexOfQuery); + queryString = wholePath.substring(indexOfQuery + 1); + } + path = resolveDotsInPath(path); + } + + // Find last path component. + var lastPathComponent = null; + if (path && path !== "/") { + // Skip the trailing slash if there is one. + var endOffset = path[path.length - 1] === "/" ? 1 : 0; + var lastSlashIndex = path.lastIndexOf("/", path.length - 1 - endOffset); + if (lastSlashIndex !== -1) + lastPathComponent = path.substring(lastSlashIndex + 1, path.length - endOffset); + } + + return {scheme, host, port, path, queryString, fragment, lastPathComponent}; +} + +function absoluteURL(partialURL, baseURL) +{ + partialURL = partialURL ? partialURL.trim() : ""; + + // Return data and javascript URLs as-is. + if (partialURL.startsWith("data:") || partialURL.startsWith("javascript:") || partialURL.startsWith("mailto:")) + return partialURL; + + // If the URL has a scheme it is already a full URL, so return it. + if (parseURL(partialURL).scheme) + return partialURL; + + // If there is no partial URL, just return the base URL. + if (!partialURL) + return baseURL || null; + + var baseURLComponents = parseURL(baseURL); + + // The base URL needs to be an absolute URL. Return null if it isn't. + if (!baseURLComponents.scheme) + return null; + + // A URL that starts with "//" is a full URL without the scheme. Use the base URL scheme. + if (partialURL[0] === "/" && partialURL[1] === "/") + return baseURLComponents.scheme + ":" + partialURL; + + // The path can be null for URLs that have just a scheme and host (like "http://apple.com"). So make the path be "/". + if (!baseURLComponents.path) + baseURLComponents.path = "/"; + + // Generate the base URL prefix that is used in the rest of the cases. + var baseURLPrefix = baseURLComponents.scheme + "://" + baseURLComponents.host + (baseURLComponents.port ? (":" + baseURLComponents.port) : ""); + + // A URL that starts with "?" is just a query string that gets applied to the base URL (replacing the base URL query string and fragment). + if (partialURL[0] === "?") + return baseURLPrefix + baseURLComponents.path + partialURL; + + // A URL that starts with "/" is an absolute path that gets applied to the base URL (replacing the base URL path, query string and fragment). + if (partialURL[0] === "/") + return baseURLPrefix + resolveDotsInPath(partialURL); + + // A URL that starts with "#" is just a fragment that gets applied to the base URL (replacing the base URL fragment, maintaining the query string). + if (partialURL[0] === "#") { + let queryStringComponent = baseURLComponents.queryString ? "?" + baseURLComponents.queryString : ""; + return baseURLPrefix + baseURLComponents.path + queryStringComponent + partialURL; + } + + // Generate the base path that is used in the final case by removing everything after the last "/" from the base URL's path. + var basePath = baseURLComponents.path.substring(0, baseURLComponents.path.lastIndexOf("/")) + "/"; + return baseURLPrefix + resolveDotsInPath(basePath + partialURL); +} + +function parseLocationQueryParameters(arrayResult) +{ + // The first character is always the "?". + return parseQueryString(window.location.search.substring(1), arrayResult); +} + +function parseQueryString(queryString, arrayResult) +{ + if (!queryString) + return arrayResult ? [] : {}; + + function decode(string) + { + try { + // Replace "+" with " " then decode percent encoded values. + return decodeURIComponent(string.replace(/\+/g, " ")); + } catch (e) { + return string; + } + } + + var parameters = arrayResult ? [] : {}; + var parameterStrings = queryString.split("&"); + for (var i = 0; i < parameterStrings.length; ++i) { + var pair = parameterStrings[i].split("=").map(decode); + if (arrayResult) + parameters.push({name: pair[0], value: pair[1]}); + else + parameters[pair[0]] = pair[1]; + } + + return parameters; +} + +WebInspector.displayNameForURL = function(url, urlComponents) +{ + if (url.startsWith("data:")) + return WebInspector.truncateURL(url); + + if (!urlComponents) + urlComponents = parseURL(url); + + var displayName; + try { + displayName = decodeURIComponent(urlComponents.lastPathComponent || ""); + } catch (e) { + displayName = urlComponents.lastPathComponent; + } + + return displayName || WebInspector.displayNameForHost(urlComponents.host) || url; +}; + +WebInspector.truncateURL = function(url, multiline = false, dataURIMaxSize = 6) +{ + if (!url.startsWith("data:")) + return url; + + const dataIndex = url.indexOf(",") + 1; + let header = url.slice(0, dataIndex); + if (multiline) + header += "\n"; + + const data = url.slice(dataIndex); + if (data.length < dataURIMaxSize) + return header + data; + + const firstChunk = data.slice(0, Math.ceil(dataURIMaxSize / 2)); + const ellipsis = "\u2026"; + const middleChunk = multiline ? `\n${ellipsis}\n` : ellipsis; + const lastChunk = data.slice(-Math.floor(dataURIMaxSize / 2)); + return header + firstChunk + middleChunk + lastChunk; +}; + +WebInspector.displayNameForHost = function(host) +{ + // FIXME <rdar://problem/11237413>: This should decode punycode hostnames. + return host; +}; |