tor-browser

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

AboutPrivateBrowsingParent.sys.mjs (5771B)


      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
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { ASRouter } from "resource:///modules/asrouter/ASRouter.sys.mjs";
      6 import { BrowserUtils } from "resource://gre/modules/BrowserUtils.sys.mjs";
      7 import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
      8 
      9 const SHOWN_PREF = "browser.search.separatePrivateDefault.ui.banner.shown";
     10 const lazy = {};
     11 XPCOMUtils.defineLazyPreferenceGetter(
     12  lazy,
     13  "MAX_SEARCH_BANNER_SHOW_COUNT",
     14  "browser.search.separatePrivateDefault.ui.banner.max",
     15  0
     16 );
     17 
     18 XPCOMUtils.defineLazyPreferenceGetter(
     19  lazy,
     20  "isPrivateSearchUIEnabled",
     21  "browser.search.separatePrivateDefault.ui.enabled",
     22  false
     23 );
     24 
     25 ChromeUtils.defineESModuleGetters(lazy, {
     26  SpecialMessageActions:
     27    "resource://messaging-system/lib/SpecialMessageActions.sys.mjs",
     28 });
     29 
     30 // We only show the private search banner once per browser session.
     31 let gSearchBannerShownThisSession;
     32 
     33 export class AboutPrivateBrowsingParent extends JSWindowActorParent {
     34  // Used by tests
     35  static setShownThisSession(shown) {
     36    gSearchBannerShownThisSession = shown;
     37  }
     38 
     39  receiveMessage(aMessage) {
     40    let browser = this.browsingContext.top.embedderElement;
     41    if (!browser) {
     42      return undefined;
     43    }
     44 
     45    let win = browser.ownerGlobal;
     46 
     47    switch (aMessage.name) {
     48      case "OpenPrivateWindow": {
     49        win.OpenBrowserWindow({ private: true });
     50        break;
     51      }
     52      case "OpenSearchPreferences": {
     53        win.openPreferences("search", { origin: "about-privatebrowsing" });
     54        break;
     55      }
     56      case "SearchHandoff": {
     57        let urlBar = win.gURLBar;
     58        let searchEngine = Services.search.defaultPrivateEngine;
     59        let isFirstChange = true;
     60 
     61        if (!aMessage.data || !aMessage.data.text) {
     62          urlBar.setHiddenFocus();
     63        } else {
     64          // Pass the provided text to the awesomebar
     65          urlBar.handoff(aMessage.data.text, searchEngine);
     66          isFirstChange = false;
     67        }
     68 
     69        let checkFirstChange = () => {
     70          // Check if this is the first change since we hidden focused. If it is,
     71          // remove hidden focus styles, prepend the search alias and hide the
     72          // in-content search.
     73          if (isFirstChange) {
     74            isFirstChange = false;
     75            urlBar.removeHiddenFocus(true);
     76            urlBar.handoff("", searchEngine);
     77            this.sendAsyncMessage("DisableSearch");
     78            urlBar.removeEventListener("compositionstart", checkFirstChange);
     79            urlBar.removeEventListener("paste", checkFirstChange);
     80          }
     81        };
     82 
     83        let onKeydown = ev => {
     84          // Check if the keydown will cause a value change.
     85          if (ev.key.length === 1 && !ev.altKey && !ev.ctrlKey && !ev.metaKey) {
     86            checkFirstChange();
     87          }
     88          // If the Esc button is pressed, we are done. Show in-content search and cleanup.
     89          if (ev.key === "Escape") {
     90            onDone();
     91          }
     92        };
     93 
     94        let onDone = ev => {
     95          // We are done. Show in-content search again and cleanup.
     96          this.sendAsyncMessage("ShowSearch");
     97 
     98          const forceSuppressFocusBorder = ev?.type === "mousedown";
     99          urlBar.removeHiddenFocus(forceSuppressFocusBorder);
    100 
    101          urlBar.removeEventListener("keydown", onKeydown);
    102          urlBar.removeEventListener("mousedown", onDone);
    103          urlBar.removeEventListener("blur", onDone);
    104          urlBar.removeEventListener("compositionstart", checkFirstChange);
    105          urlBar.removeEventListener("paste", checkFirstChange);
    106        };
    107 
    108        urlBar.addEventListener("keydown", onKeydown);
    109        urlBar.addEventListener("mousedown", onDone);
    110        urlBar.addEventListener("blur", onDone);
    111        urlBar.addEventListener("compositionstart", checkFirstChange);
    112        urlBar.addEventListener("paste", checkFirstChange);
    113        break;
    114      }
    115      case "ShouldShowSearchBanner": {
    116        // If this is a pre-loaded private browsing new tab, then we don't want
    117        // to display the banner - it might never get displayed to the user
    118        // and we won't know, or it might get displayed at the wrong time.
    119        // This has the minor downside of not displaying the banner if
    120        // you go into private browsing via opening a link, and then opening
    121        // a new tab, we won't display the banner, for now, that's ok.
    122        if (browser.getAttribute("preloadedState") === "preloaded") {
    123          return null;
    124        }
    125 
    126        if (!lazy.isPrivateSearchUIEnabled || gSearchBannerShownThisSession) {
    127          return null;
    128        }
    129        gSearchBannerShownThisSession = true;
    130        const shownTimes = Services.prefs.getIntPref(SHOWN_PREF, 0);
    131        if (shownTimes >= lazy.MAX_SEARCH_BANNER_SHOW_COUNT) {
    132          return null;
    133        }
    134        Services.prefs.setIntPref(SHOWN_PREF, shownTimes + 1);
    135        return new Promise(resolve => {
    136          Services.search.getDefaultPrivate().then(engine => {
    137            resolve(engine.name);
    138          });
    139        });
    140      }
    141      case "SearchBannerDismissed": {
    142        Services.prefs.setIntPref(
    143          SHOWN_PREF,
    144          lazy.MAX_SEARCH_BANNER_SHOW_COUNT
    145        );
    146        break;
    147      }
    148      case "ShouldShowPromo": {
    149        return BrowserUtils.shouldShowPromo(
    150          BrowserUtils.PromoType[aMessage.data.type]
    151        );
    152      }
    153      case "SpecialMessageActionDispatch": {
    154        lazy.SpecialMessageActions.handleAction(aMessage.data, browser);
    155        break;
    156      }
    157      case "IsPromoBlocked": {
    158        return !ASRouter.isUnblockedMessage(aMessage.data);
    159      }
    160    }
    161 
    162    return undefined;
    163  }
    164 }