1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5const { XPCOMUtils } = ChromeUtils.import(
6  "resource://gre/modules/XPCOMUtils.jsm"
7);
8const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
9
10XPCOMUtils.defineLazyServiceGetter(
11  this,
12  "IDNService",
13  "@mozilla.org/network/idn-service;1",
14  "nsIIDNService"
15);
16
17XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]);
18
19/**
20 * Properly convert internationalized domain names.
21 * @param {string} host Domain hostname.
22 * @returns {string} Hostname suitable to be displayed.
23 */
24function handleIDNHost(hostname) {
25  try {
26    return IDNService.convertToDisplayIDN(hostname, {});
27  } catch (e) {
28    // If something goes wrong (e.g. host is an IP address) just fail back
29    // to the full domain.
30    return hostname;
31  }
32}
33
34/**
35 * Get the effective top level domain of a host.
36 * @param {string} host The host to be analyzed.
37 * @return {str} The suffix or empty string if there's no suffix.
38 */
39function getETLD(host) {
40  try {
41    return Services.eTLD.getPublicSuffixFromHost(host);
42  } catch (err) {
43    return "";
44  }
45}
46
47/**
48 * shortURL - Creates a short version of a link's url, used for display purposes
49 *            e.g. {url: http://www.foosite.com}  =>  "foosite"
50 *
51 * @param  {obj} link A link object
52 *         {str} link.url (required)- The url of the link
53 * @return {str}   A short url
54 */
55function shortURL({ url }) {
56  if (!url) {
57    return "";
58  }
59
60  // Make sure we have a valid / parseable url
61  let parsed;
62  try {
63    parsed = new URL(url);
64  } catch (ex) {
65    // Not entirely sure what we have, but just give it back
66    return url;
67  }
68
69  // Clean up the url (lowercase hostname via URL and remove www.)
70  const hostname = parsed.hostname.replace(/^www\./i, "");
71
72  // Remove the eTLD (e.g., com, net) and the preceding period from the hostname
73  const eTLD = getETLD(hostname);
74  const eTLDExtra = eTLD.length ? -(eTLD.length + 1) : Infinity;
75
76  // Ideally get the short eTLD-less host but fall back to longer url parts
77  return (
78    handleIDNHost(hostname.slice(0, eTLDExtra) || hostname) ||
79    parsed.pathname ||
80    parsed.href
81  );
82}
83
84const EXPORTED_SYMBOLS = ["shortURL", "getETLD"];
85