tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ext-topSites.js (4719B)


      1 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
      2 /* vim: set sts=2 sw=2 et tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 "use strict";
      8 
      9 ChromeUtils.defineESModuleGetters(this, {
     10  AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs",
     11  NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs",
     12  getSearchProvider:
     13    "moz-src:///toolkit/components/search/SearchShortcuts.sys.mjs",
     14 });
     15 
     16 const SHORTCUTS_PREF =
     17  "browser.newtabpage.activity-stream.improvesearch.topSiteSearchShortcuts";
     18 const TOPSITES_FEED_PREF =
     19  "browser.newtabpage.activity-stream.feeds.system.topsites";
     20 
     21 this.topSites = class extends ExtensionAPI {
     22  getAPI() {
     23    return {
     24      topSites: {
     25        get: async function (options) {
     26          // We fallback to newtab = false behavior if the user disabled their
     27          // Top Sites feed.
     28          let getNewtabSites =
     29            options.newtab &&
     30            Services.prefs.getBoolPref(TOPSITES_FEED_PREF, false);
     31          let links = getNewtabSites
     32            ? AboutNewTab.getTopSites()
     33            : await NewTabUtils.activityStreamLinks.getTopSites({
     34                ignoreBlocked: options.includeBlocked,
     35                onePerDomain: options.onePerDomain,
     36                numItems: options.limit,
     37                includeFavicon: options.includeFavicon,
     38              });
     39 
     40          if (options.includePinned && !getNewtabSites) {
     41            let pinnedLinks = NewTabUtils.pinnedLinks.links;
     42            if (options.includeFavicon) {
     43              pinnedLinks =
     44                NewTabUtils.activityStreamProvider._faviconBytesToDataURI(
     45                  await NewTabUtils.activityStreamProvider._addFavicons(
     46                    pinnedLinks
     47                  )
     48                );
     49            }
     50            pinnedLinks.forEach((pinnedLink, index) => {
     51              if (
     52                pinnedLink &&
     53                (!pinnedLink.searchTopSite || options.includeSearchShortcuts)
     54              ) {
     55                // Remove any dupes from history.
     56                links = links.filter(
     57                  link =>
     58                    link.url != pinnedLink.url &&
     59                    (!options.onePerDomain ||
     60                      NewTabUtils.extractSite(link.url) !=
     61                        pinnedLink.baseDomain)
     62                );
     63                links.splice(index, 0, pinnedLink);
     64              }
     65            });
     66          }
     67 
     68          // Convert links to search shortcuts, if necessary.
     69          if (
     70            options.includeSearchShortcuts &&
     71            Services.prefs.getBoolPref(SHORTCUTS_PREF, false) &&
     72            !getNewtabSites
     73          ) {
     74            // Pinned shortcuts are already returned as searchTopSite links,
     75            // with a proper label and url. But certain non-pinned links may
     76            // also be promoted to search shortcuts; here we convert them.
     77            links = links.map(link => {
     78              let searchProvider = getSearchProvider(
     79                NewTabUtils.shortURL(link)
     80              );
     81              if (searchProvider) {
     82                link.searchTopSite = true;
     83                link.label = searchProvider.keyword;
     84                link.url = searchProvider.url;
     85              }
     86              return link;
     87            });
     88          }
     89 
     90          // Because we may have added links, we must crop again.
     91          if (typeof options.limit == "number") {
     92            links = links.slice(0, options.limit);
     93          }
     94 
     95          const makeDataURI = url => url && ExtensionUtils.makeDataURI(url);
     96 
     97          return Promise.all(
     98            links.map(async link => ({
     99              type: link.searchTopSite ? "search" : "url",
    100              url: link.url,
    101              // The newtab page allows the user to set custom site titles, which
    102              // are stored in `label`, so prefer it.  Search top sites currently
    103              // don't have titles but `hostname` instead.
    104              title: link.label || link.title || link.hostname || "",
    105              // Default top sites don't have a favicon property.  Instead they
    106              // have tippyTopIcon, a 96x96pt image used on the newtab page.
    107              // We'll use it as the favicon for now, but ideally default top
    108              // sites would have real favicons.  Non-default top sites (i.e.,
    109              // those from the user's history) will have favicons.
    110              favicon: options.includeFavicon
    111                ? link.favicon || (await makeDataURI(link.tippyTopIcon)) || null
    112                : null,
    113            }))
    114          );
    115        },
    116      },
    117    };
    118  }
    119 };