Bug 1448553 - Part 1: Defines common functions for getting a Unicode URL or a Unicode URL component r?nchevobbe
This patch defines some common functions for getting a Unicode URL or a Unicode
URL component.
These functions are not only intended to be used by future patches for this bug,
but also intended to be the common functions for any future patches which need
to reuse such functionalities.
MozReview-Commit-ID: DZBYoKv9Fmx
--- a/devtools/client/shared/moz.build
+++ b/devtools/client/shared/moz.build
@@ -48,16 +48,17 @@ DevToolsModules(
'scroll.js',
'source-utils.js',
'SplitView.jsm',
'stylesheet-utils.js',
'suggestion-picker.js',
'telemetry.js',
'theme.js',
'undo.js',
+ 'unicode-url.js',
'view-source.js',
'webgl-utils.js',
'zoom-keys.js',
)
with Files('**'):
BUG_COMPONENT = ('Firefox', 'Developer Tools')
new file mode 100644
--- /dev/null
+++ b/devtools/client/shared/unicode-url.js
@@ -0,0 +1,106 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const { Cc, Ci } = require("chrome");
+const idnService =
+ Cc["@mozilla.org/network/idn-service;1"].getService(Ci.nsIIDNService);
+
+/**
+ * Gets a readble Unicode hostname from a hostname.
+ *
+ * If the `hostname` is a readable ASCII hostname, such as example.org, then
+ * this function will simply return the original `hostname`.
+ *
+ * If the `hostname` is a Punycode hostname representing a Unicode domain name,
+ * such as xn--g6w.xn--8pv, then this function will return the readable Unicode
+ * domain name by decoding the Punycode hostname.
+ *
+ * @param {string} hostname
+ * the hostname from which the Unicode hostname will be
+ * parsed, such as example.org, xn--g6w.xn--8pv.
+ * @return {string} The Unicode hostname. It may be the same as the `hostname`
+ * passed to this function if the `hostname` itself is
+ * a readable ASCII hostname or a Unicode hostname.
+ */
+function getUnicodeHostname(hostname) {
+ return idnService.convertToDisplayIDN(hostname, {});
+}
+
+/**
+ * Gets a readble Unicode URL pathname from a URL pathname.
+ *
+ * If the `urlPath` is a readable ASCII URL pathname, such as /a/b/c.js, then
+ * this function will simply return the original `urlPath`.
+ *
+ * If the `urlPath` is a URI-encoded pathname, such as %E8%A9%A6/%E6%B8%AC.js,
+ * then this function will return the readable Unicode pathname.
+ *
+ * If the `urlPath` is a malformed URL pathname, then this function will simply
+ * return the original `urlPath`.
+ *
+ * @param {string} urlPath
+ * the URL path from which the Unicode URL path will be parsed,
+ * such as /a/b/c.js, %E8%A9%A6/%E6%B8%AC.js.
+ * @return {string} The Unicode URL Path. It may be the same as the `urlPath`
+ * passed to this function if the `urlPath` itself is a readable
+ * ASCII url or a Unicode url.
+ */
+function getUnicodeUrlPath(urlPath) {
+ try {
+ return decodeURIComponent(urlPath);
+ } catch (err) {
+ dump("Warning: getUnicodeUrlPath failed to get a Unicode URL from" +
+ `${urlPath}, reason: ${err}`);
+ }
+ return urlPath;
+}
+
+/**
+ * Gets a readable Unicode URL from a URL.
+ *
+ * If the `url` is a readable ASCII URL, such as http://example.org/a/b/c.js,
+ * then this function will simply return the original `url`.
+ *
+ * If the `url` includes either an unreadable Punycode domain name or an
+ * unreadable URI-encoded pathname, such as
+ * http://xn--g6w.xn--8pv/%E8%A9%A6/%E6%B8%AC.js, then this function will return
+ * the readable URL by decoding all its unreadable URL components to Unicode
+ * characters.
+ *
+ * If the `url` is a malformed URL, then this function will return the original
+ * `url`.
+ *
+ * If the `url` is a data: URI, then this function will return the original
+ * `url`.
+ *
+ * @param {string} url
+ * the full URL, or a data: URI. from which the readable URL
+ * will be parsed, such as, http://example.org/a/b/c.js,
+ * http://xn--g6w.xn--8pv/%E8%A9%A6/%E6%B8%AC.js
+ * @return {string} The readable URL. It may be the same as the `url` passed to
+ * this function if the `url` itself is readable.
+ */
+function getUnicodeUrl(url) {
+ try {
+ const { protocol, hostname } = new URL(url);
+ if (protocol === "data:") {
+ // Never convert a data: URI.
+ return url;
+ }
+ const readableHostname = getUnicodeHostname(hostname);
+ url = decodeURIComponent(url);
+ return url.replace(hostname, readableHostname);
+ } catch (err) {
+ dump("Warning: getUnicodeUrl failed to get a Unicode URL from" +
+ `${url}, reason: ${err}`);
+ }
+ return url;
+}
+
+module.exports = {
+ getUnicodeHostname,
+ getUnicodeUrlPath,
+ getUnicodeUrl,
+};