Bug 1448553 - Part 1: Defines common functions for getting a Unicode URL or a Unicode URL component r?nchevobbe draft
authorZhang Junzhi <zjz@zjz.name>
Mon, 02 Apr 2018 14:36:13 +0800
changeset 780905 3916268da9423947bb80d0b69ea217d273298c50
parent 780587 cfe6399e142c71966ef58a16cfd52c0b46dc6b1e
child 780906 5e680208cb2eb24f8805d37499f112b4ed9dcfec
push id106159
push userbmo:zjz@zjz.name
push dateThu, 12 Apr 2018 07:30:36 +0000
reviewersnchevobbe
bugs1448553
milestone61.0a1
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
devtools/client/shared/moz.build
devtools/client/shared/unicode-url.js
--- 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,
+};