Pier Angelo Vendrame pushed to branch base-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Tor Browser

Commits:

5 changed files:

Changes:

  • browser/components/BrowserComponents.manifest
    ... ... @@ -50,6 +50,8 @@ category browser-first-window-ready resource://gre/modules/CaptchaDetectionPingU
    50 50
     category browser-first-window-ready resource://gre/modules/SandboxUtils.sys.mjs SandboxUtils.maybeWarnAboutMissingUserNamespaces
    
    51 51
     #endif
    
    52 52
     #endif
    
    53
    +category browser-first-window-ready moz-src:///browser/modules/ClipboardPrivacy.sys.mjs ClipboardPrivacy.init
    
    54
    +category browser-first-window-ready moz-src:///browser/modules/SecurityLevelRestartNotification.sys.mjs SecurityLevelRestartNotification.ready
    
    53 55
     
    
    54 56
     category browser-idle-startup resource:///modules/PlacesUIUtils.sys.mjs PlacesUIUtils.unblockToolbars
    
    55 57
     category browser-idle-startup resource:///modules/BuiltInThemes.sys.mjs BuiltInThemes.ensureBuiltInThemes
    

  • browser/components/BrowserGlue.sys.mjs
    ... ... @@ -12,7 +12,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
    12 12
       AWToolbarButton: "resource:///modules/aboutwelcome/AWToolbarUtils.sys.mjs",
    
    13 13
       ASRouter: "resource:///modules/asrouter/ASRouter.sys.mjs",
    
    14 14
       AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
    
    15
    -  AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
    
    16 15
       BackupService: "resource:///modules/backup/BackupService.sys.mjs",
    
    17 16
       BrowserSearchTelemetry:
    
    18 17
         "moz-src:///browser/components/search/BrowserSearchTelemetry.sys.mjs",
    
    ... ... @@ -61,8 +60,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
    61 60
       ScreenshotsUtils: "resource:///modules/ScreenshotsUtils.sys.mjs",
    
    62 61
       SearchSERPTelemetry:
    
    63 62
         "moz-src:///browser/components/search/SearchSERPTelemetry.sys.mjs",
    
    64
    -  SecurityLevelRestartNotification:
    
    65
    -    "resource:///modules/SecurityLevelRestartNotification.sys.mjs",
    
    66 63
       SessionStartup: "resource:///modules/sessionstore/SessionStartup.sys.mjs",
    
    67 64
       SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
    
    68 65
       ShortcutUtils: "resource://gre/modules/ShortcutUtils.sys.mjs",
    
    ... ... @@ -106,170 +103,6 @@ if (AppConstants.ENABLE_WEBDRIVER) {
    106 103
     
    
    107 104
     const PREF_PDFJS_ISDEFAULT_CACHE_STATE = "pdfjs.enabledCache.state";
    
    108 105
     
    
    109
    -// Empty clipboard content from private windows on exit
    
    110
    -// (tor-browser#42154)
    
    111
    -const ClipboardPrivacy = {
    
    112
    -  _lastClipboardHash: null,
    
    113
    -  _globalActivation: false,
    
    114
    -  _isPrivateClipboard: false,
    
    115
    -  _hasher: null,
    
    116
    -  _shuttingDown: false,
    
    117
    -  _log: null,
    
    118
    -
    
    119
    -  _createTransferable() {
    
    120
    -    const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
    
    121
    -      Ci.nsITransferable
    
    122
    -    );
    
    123
    -    trans.init(null);
    
    124
    -    return trans;
    
    125
    -  },
    
    126
    -  _computeClipboardHash() {
    
    127
    -    const flavors = ["text/x-moz-url", "text/plain"];
    
    128
    -    if (
    
    129
    -      !Services.clipboard.hasDataMatchingFlavors(
    
    130
    -        flavors,
    
    131
    -        Ci.nsIClipboard.kGlobalClipboard
    
    132
    -      )
    
    133
    -    ) {
    
    134
    -      return null;
    
    135
    -    }
    
    136
    -    const trans = this._createTransferable();
    
    137
    -    flavors.forEach(trans.addDataFlavor);
    
    138
    -    try {
    
    139
    -      Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
    
    140
    -      const clipboardContent = {};
    
    141
    -      trans.getAnyTransferData({}, clipboardContent);
    
    142
    -      const { data } = clipboardContent.value.QueryInterface(
    
    143
    -        Ci.nsISupportsString
    
    144
    -      );
    
    145
    -      const bytes = new TextEncoder().encode(data);
    
    146
    -      const hasher = (this._hasher ||= Cc[
    
    147
    -        "@mozilla.org/security/hash;1"
    
    148
    -      ].createInstance(Ci.nsICryptoHash));
    
    149
    -      hasher.init(hasher.SHA256);
    
    150
    -      hasher.update(bytes, bytes.length);
    
    151
    -      return hasher.finish(true);
    
    152
    -    } catch (e) {}
    
    153
    -    return null;
    
    154
    -  },
    
    155
    -
    
    156
    -  startup() {
    
    157
    -    this._log = console.createInstance({
    
    158
    -      prefix: "ClipboardPrivacy",
    
    159
    -    });
    
    160
    -    this._lastClipboardHash = this._computeClipboardHash();
    
    161
    -
    
    162
    -    // Here we track changes in active window / application,
    
    163
    -    // by filtering focus events and window closures.
    
    164
    -    const handleActivation = (win, activation) => {
    
    165
    -      if (activation) {
    
    166
    -        if (!this._globalActivation) {
    
    167
    -          // focus changed within this window, bail out.
    
    168
    -          return;
    
    169
    -        }
    
    170
    -        this._globalActivation = false;
    
    171
    -      } else if (!Services.focus.activeWindow) {
    
    172
    -        // focus is leaving this window:
    
    173
    -        // let's track whether it remains within the browser.
    
    174
    -        lazy.setTimeout(() => {
    
    175
    -          this._globalActivation = !Services.focus.activeWindow;
    
    176
    -        }, 100);
    
    177
    -      }
    
    178
    -
    
    179
    -      const checkClipboardContent = () => {
    
    180
    -        const clipboardHash = this._computeClipboardHash();
    
    181
    -        if (clipboardHash !== this._lastClipboardHash) {
    
    182
    -          this._isPrivateClipboard =
    
    183
    -            !activation &&
    
    184
    -            (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing ||
    
    185
    -              lazy.PrivateBrowsingUtils.isWindowPrivate(win));
    
    186
    -          this._lastClipboardHash = clipboardHash;
    
    187
    -          this._log.debug(
    
    188
    -            `Clipboard changed: private ${this._isPrivateClipboard}, hash ${clipboardHash}.`
    
    189
    -          );
    
    190
    -        }
    
    191
    -      };
    
    192
    -
    
    193
    -      if (win.closed) {
    
    194
    -        checkClipboardContent();
    
    195
    -      } else {
    
    196
    -        // defer clipboard access on DOM events to work-around tor-browser#42306
    
    197
    -        lazy.setTimeout(checkClipboardContent, 0);
    
    198
    -      }
    
    199
    -    };
    
    200
    -    const focusListener = e =>
    
    201
    -      e.isTrusted && handleActivation(e.currentTarget, e.type === "focusin");
    
    202
    -    const initWindow = win => {
    
    203
    -      for (const e of ["focusin", "focusout"]) {
    
    204
    -        win.addEventListener(e, focusListener);
    
    205
    -      }
    
    206
    -    };
    
    207
    -    for (const w of Services.ww.getWindowEnumerator()) {
    
    208
    -      initWindow(w);
    
    209
    -    }
    
    210
    -    Services.ww.registerNotification((win, event) => {
    
    211
    -      switch (event) {
    
    212
    -        case "domwindowopened":
    
    213
    -          initWindow(win);
    
    214
    -          break;
    
    215
    -        case "domwindowclosed":
    
    216
    -          handleActivation(win, false);
    
    217
    -          if (
    
    218
    -            this._isPrivateClipboard &&
    
    219
    -            lazy.PrivateBrowsingUtils.isWindowPrivate(win) &&
    
    220
    -            (this._shuttingDown ||
    
    221
    -              !Array.from(Services.ww.getWindowEnumerator()).find(
    
    222
    -                w =>
    
    223
    -                  lazy.PrivateBrowsingUtils.isWindowPrivate(w) &&
    
    224
    -                  // We need to filter out the HIDDEN WebExtensions window,
    
    225
    -                  // which might be private as well but is not UI-relevant.
    
    226
    -                  !w.location.href.startsWith("chrome://extensions/")
    
    227
    -              ))
    
    228
    -          ) {
    
    229
    -            // no more private windows, empty private content if needed
    
    230
    -            this.emptyPrivate();
    
    231
    -          }
    
    232
    -      }
    
    233
    -    });
    
    234
    -
    
    235
    -    lazy.AsyncShutdown.quitApplicationGranted.addBlocker(
    
    236
    -      "ClipboardPrivacy: removing private data",
    
    237
    -      () => {
    
    238
    -        this._shuttingDown = true;
    
    239
    -        this.emptyPrivate();
    
    240
    -      }
    
    241
    -    );
    
    242
    -  },
    
    243
    -  emptyPrivate() {
    
    244
    -    if (
    
    245
    -      this._isPrivateClipboard &&
    
    246
    -      !Services.prefs.getBoolPref(
    
    247
    -        "browser.privatebrowsing.preserveClipboard",
    
    248
    -        false
    
    249
    -      ) &&
    
    250
    -      this._lastClipboardHash === this._computeClipboardHash()
    
    251
    -    ) {
    
    252
    -      // nsIClipboard.emptyClipboard() does nothing in Wayland:
    
    253
    -      // we'll set an empty string as a work-around.
    
    254
    -      const trans = this._createTransferable();
    
    255
    -      const flavor = "text/plain";
    
    256
    -      trans.addDataFlavor(flavor);
    
    257
    -      const emptyString = Cc["@mozilla.org/supports-string;1"].createInstance(
    
    258
    -        Ci.nsISupportsString
    
    259
    -      );
    
    260
    -      emptyString.data = "";
    
    261
    -      trans.setTransferData(flavor, emptyString);
    
    262
    -      const { clipboard } = Services,
    
    263
    -        { kGlobalClipboard } = clipboard;
    
    264
    -      clipboard.setData(trans, null, kGlobalClipboard);
    
    265
    -      clipboard.emptyClipboard(kGlobalClipboard);
    
    266
    -      this._lastClipboardHash = null;
    
    267
    -      this._isPrivateClipboard = false;
    
    268
    -      this._log.info("Private clipboard emptied.");
    
    269
    -    }
    
    270
    -  },
    
    271
    -};
    
    272
    -
    
    273 106
     ChromeUtils.defineLazyGetter(
    
    274 107
       lazy,
    
    275 108
       "WeaveService",
    
    ... ... @@ -596,9 +429,7 @@ BrowserGlue.prototype = {
    596 429
     
    
    597 430
         // handle any UI migration
    
    598 431
         this._migrateUI();
    
    599
    -
    
    600
    -    // Base Browser-specific version of _migrateUI.
    
    601
    -    this._migrateUIBB();
    
    432
    +    lazy.ProfileDataUpgrader.upgradeBB(this._isNewProfile);
    
    602 433
     
    
    603 434
         if (!Services.prefs.prefHasUserValue(PREF_PDFJS_ISDEFAULT_CACHE_STATE)) {
    
    604 435
           lazy.PdfJs.checkIsDefault(this._isNewProfile);
    
    ... ... @@ -984,10 +815,6 @@ BrowserGlue.prototype = {
    984 815
           lazy.WeaveService.init();
    
    985 816
         }
    
    986 817
     
    
    987
    -    lazy.SecurityLevelRestartNotification.ready();
    
    988
    -
    
    989
    -    ClipboardPrivacy.startup();
    
    990
    -
    
    991 818
         lazy.BrowserUtils.callModulesFromCategory(
    
    992 819
           {
    
    993 820
             categoryName: "browser-first-window-ready",
    
    ... ... @@ -1823,83 +1650,6 @@ BrowserGlue.prototype = {
    1823 1650
         }
    
    1824 1651
       },
    
    1825 1652
     
    
    1826
    -  _migrateUIBB() {
    
    1827
    -    // Version 1: 13.0a3. Reset layout.css.prefers-color-scheme.content-override
    
    1828
    -    //            for tor-browser#41739.
    
    1829
    -    // Version 2: 14.0a5: Reset the privacy tracking headers preferences since
    
    1830
    -    //            the UI is hidden. tor-browser#42777.
    
    1831
    -    //            Also, do not set
    
    1832
    -    //            dom.security.https_only_mode_send_http_background_request in
    
    1833
    -    //            the security level anymore (tor-browser#42149).
    
    1834
    -    //            Also, reset security.xfocsp.errorReporting.automatic since we
    
    1835
    -    //            hid its neterror checkbox. tor-browser#42653.
    
    1836
    -    // Version 3: 14.0a7: Reset general.smoothScroll. tor-browser#42070.
    
    1837
    -    // Version 4: 15.0a2: Drop ML components. tor-browser#44045.
    
    1838
    -    const MIGRATION_VERSION = 4;
    
    1839
    -    const MIGRATION_PREF = "basebrowser.migration.version";
    
    1840
    -    if (this._isNewProfile) {
    
    1841
    -      // Do not migrate fresh profiles
    
    1842
    -      Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
    
    1843
    -      return;
    
    1844
    -    } else if (this._isNewProfile === undefined) {
    
    1845
    -      // If this happens, check if upstream updated their function and do not
    
    1846
    -      // set this member anymore!
    
    1847
    -      console.error("_migrateUIBB: this._isNewProfile is undefined.");
    
    1848
    -    }
    
    1849
    -    // We do not care whether this is a new or old profile, since in version 1
    
    1850
    -    // we just quickly clear a user preference, which should not do anything to
    
    1851
    -    // new profiles.
    
    1852
    -    // Shall we ever raise the version number and have a watershed, we can add
    
    1853
    -    // a check easily (any version > 0 will be an old profile).
    
    1854
    -    const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
    
    1855
    -    if (currentVersion < 1) {
    
    1856
    -      Services.prefs.clearUserPref(
    
    1857
    -        "layout.css.prefers-color-scheme.content-override"
    
    1858
    -      );
    
    1859
    -    }
    
    1860
    -    if (currentVersion < 2) {
    
    1861
    -      for (const prefName of [
    
    1862
    -        "privacy.globalprivacycontrol.enabled",
    
    1863
    -        "privacy.donottrackheader.enabled",
    
    1864
    -        // Telemetry preference for if the user changed the value.
    
    1865
    -        "privacy.globalprivacycontrol.was_ever_enabled",
    
    1866
    -        // The next two preferences have no corresponding UI, but are related.
    
    1867
    -        "privacy.globalprivacycontrol.functionality.enabled",
    
    1868
    -        "privacy.globalprivacycontrol.pbmode.enabled",
    
    1869
    -        "dom.security.https_only_mode_send_http_background_request",
    
    1870
    -        "security.xfocsp.errorReporting.automatic",
    
    1871
    -      ]) {
    
    1872
    -        Services.prefs.clearUserPref(prefName);
    
    1873
    -      }
    
    1874
    -    }
    
    1875
    -    if (currentVersion < 3) {
    
    1876
    -      Services.prefs.clearUserPref("general.smoothScroll");
    
    1877
    -    }
    
    1878
    -    if (currentVersion < 4) {
    
    1879
    -      for (const prefName of [
    
    1880
    -        "browser.translations.enable",
    
    1881
    -        "browser.ml.enable",
    
    1882
    -        "browser.ml.chat.enabled",
    
    1883
    -        "browser.ml.linkPreview.enabled",
    
    1884
    -        "browser.tabs.groups.smart.enabled",
    
    1885
    -        "browser.tabs.groups.smart.userEnabled",
    
    1886
    -        "extensions.ml.enabled",
    
    1887
    -        "pdfjs.enableAltText",
    
    1888
    -        "pdfjs.enableAltTextForEnglish",
    
    1889
    -        "pdfjs.enableGuessAltText",
    
    1890
    -        "pdfjs.enableAltTextModelDownload",
    
    1891
    -        "browser.urlbar.quicksuggest.mlEnabled",
    
    1892
    -        "places.semanticHistory.featureGate",
    
    1893
    -      ]) {
    
    1894
    -        // Preferences are locked. Do not want user values to linger in the
    
    1895
    -        // user's profile and become active if these preferences become unlocked
    
    1896
    -        // in the future.
    
    1897
    -        Services.prefs.clearUserPref(prefName);
    
    1898
    -      }
    
    1899
    -    }
    
    1900
    -    Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
    
    1901
    -  },
    
    1902
    -
    
    1903 1653
       async _showUpgradeDialog() {
    
    1904 1654
         const data = await lazy.OnboardingMessageProvider.getUpgradeMessage();
    
    1905 1655
         const { gBrowser } = lazy.BrowserWindowTracker.getTopWindow();
    

  • browser/components/ProfileDataUpgrader.sys.mjs
    ... ... @@ -900,4 +900,78 @@ export let ProfileDataUpgrader = {
    900 900
         // Update the migration version.
    
    901 901
         Services.prefs.setIntPref("browser.migration.version", newVersion);
    
    902 902
       },
    
    903
    +
    
    904
    +  upgradeBB(isNewProfile) {
    
    905
    +    // Version 1: 13.0a3. Reset layout.css.prefers-color-scheme.content-override
    
    906
    +    //            for tor-browser#41739.
    
    907
    +    // Version 2: 14.0a5: Reset the privacy tracking headers preferences since
    
    908
    +    //            the UI is hidden. tor-browser#42777.
    
    909
    +    //            Also, do not set
    
    910
    +    //            dom.security.https_only_mode_send_http_background_request in
    
    911
    +    //            the security level anymore (tor-browser#42149).
    
    912
    +    //            Also, reset security.xfocsp.errorReporting.automatic since we
    
    913
    +    //            hid its neterror checkbox. tor-browser#42653.
    
    914
    +    // Version 3: 14.0a7: Reset general.smoothScroll. tor-browser#42070.
    
    915
    +    // Version 4: 15.0a2: Drop ML components. tor-browser#44045.
    
    916
    +    const MIGRATION_VERSION = 4;
    
    917
    +    const MIGRATION_PREF = "basebrowser.migration.version";
    
    918
    +
    
    919
    +    if (isNewProfile) {
    
    920
    +      // Do not migrate fresh profiles
    
    921
    +      Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
    
    922
    +      return;
    
    923
    +    } else if (isNewProfile === undefined) {
    
    924
    +      // If this happens, check if upstream updated their function and do not
    
    925
    +      // set this member anymore!
    
    926
    +      console.error("upgradeBB: isNewProfile is undefined.");
    
    927
    +    }
    
    928
    +
    
    929
    +    const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
    
    930
    +    if (currentVersion < 1) {
    
    931
    +      Services.prefs.clearUserPref(
    
    932
    +        "layout.css.prefers-color-scheme.content-override"
    
    933
    +      );
    
    934
    +    }
    
    935
    +    if (currentVersion < 2) {
    
    936
    +      for (const prefName of [
    
    937
    +        "privacy.globalprivacycontrol.enabled",
    
    938
    +        "privacy.donottrackheader.enabled",
    
    939
    +        // Telemetry preference for if the user changed the value.
    
    940
    +        "privacy.globalprivacycontrol.was_ever_enabled",
    
    941
    +        // The next two preferences have no corresponding UI, but are related.
    
    942
    +        "privacy.globalprivacycontrol.functionality.enabled",
    
    943
    +        "privacy.globalprivacycontrol.pbmode.enabled",
    
    944
    +        "dom.security.https_only_mode_send_http_background_request",
    
    945
    +        "security.xfocsp.errorReporting.automatic",
    
    946
    +      ]) {
    
    947
    +        Services.prefs.clearUserPref(prefName);
    
    948
    +      }
    
    949
    +    }
    
    950
    +    if (currentVersion < 3) {
    
    951
    +      Services.prefs.clearUserPref("general.smoothScroll");
    
    952
    +    }
    
    953
    +    if (currentVersion < 4) {
    
    954
    +      for (const prefName of [
    
    955
    +        "browser.translations.enable",
    
    956
    +        "browser.ml.enable",
    
    957
    +        "browser.ml.chat.enabled",
    
    958
    +        "browser.ml.linkPreview.enabled",
    
    959
    +        "browser.tabs.groups.smart.enabled",
    
    960
    +        "browser.tabs.groups.smart.userEnabled",
    
    961
    +        "extensions.ml.enabled",
    
    962
    +        "pdfjs.enableAltText",
    
    963
    +        "pdfjs.enableAltTextForEnglish",
    
    964
    +        "pdfjs.enableGuessAltText",
    
    965
    +        "pdfjs.enableAltTextModelDownload",
    
    966
    +        "browser.urlbar.quicksuggest.mlEnabled",
    
    967
    +        "places.semanticHistory.featureGate",
    
    968
    +      ]) {
    
    969
    +        // Preferences are locked. Do not want user values to linger in the
    
    970
    +        // user's profile and become active if these preferences become unlocked
    
    971
    +        // in the future.
    
    972
    +        Services.prefs.clearUserPref(prefName);
    
    973
    +      }
    
    974
    +    }
    
    975
    +    Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
    
    976
    +  },
    
    903 977
     };

  • browser/modules/ClipboardPrivacy.sys.mjs
    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
    +const lazy = {};
    
    6
    +
    
    7
    +ChromeUtils.defineESModuleGetters(lazy, {
    
    8
    +  AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
    
    9
    +  PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
    
    10
    +  setTimeout: "resource://gre/modules/Timer.sys.mjs",
    
    11
    +});
    
    12
    +
    
    13
    +/**
    
    14
    + * Empty clipboard content from private windows on exit.
    
    15
    + *
    
    16
    + * See tor-browser#42154.
    
    17
    + */
    
    18
    +export const ClipboardPrivacy = {
    
    19
    +  _lastClipboardHash: null,
    
    20
    +  _globalActivation: false,
    
    21
    +  _isPrivateClipboard: false,
    
    22
    +  _hasher: null,
    
    23
    +  _shuttingDown: false,
    
    24
    +  _log: null,
    
    25
    +
    
    26
    +  _createTransferable() {
    
    27
    +    const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
    
    28
    +      Ci.nsITransferable
    
    29
    +    );
    
    30
    +    trans.init(null);
    
    31
    +    return trans;
    
    32
    +  },
    
    33
    +  _computeClipboardHash() {
    
    34
    +    const flavors = ["text/x-moz-url", "text/plain"];
    
    35
    +    if (
    
    36
    +      !Services.clipboard.hasDataMatchingFlavors(
    
    37
    +        flavors,
    
    38
    +        Ci.nsIClipboard.kGlobalClipboard
    
    39
    +      )
    
    40
    +    ) {
    
    41
    +      return null;
    
    42
    +    }
    
    43
    +    const trans = this._createTransferable();
    
    44
    +    flavors.forEach(trans.addDataFlavor);
    
    45
    +    try {
    
    46
    +      Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
    
    47
    +      const clipboardContent = {};
    
    48
    +      trans.getAnyTransferData({}, clipboardContent);
    
    49
    +      const { data } = clipboardContent.value.QueryInterface(
    
    50
    +        Ci.nsISupportsString
    
    51
    +      );
    
    52
    +      const bytes = new TextEncoder().encode(data);
    
    53
    +      const hasher = (this._hasher ||= Cc[
    
    54
    +        "@mozilla.org/security/hash;1"
    
    55
    +      ].createInstance(Ci.nsICryptoHash));
    
    56
    +      hasher.init(hasher.SHA256);
    
    57
    +      hasher.update(bytes, bytes.length);
    
    58
    +      return hasher.finish(true);
    
    59
    +    } catch (e) {}
    
    60
    +    return null;
    
    61
    +  },
    
    62
    +
    
    63
    +  init() {
    
    64
    +    this._log = console.createInstance({
    
    65
    +      prefix: "ClipboardPrivacy",
    
    66
    +    });
    
    67
    +    this._lastClipboardHash = this._computeClipboardHash();
    
    68
    +
    
    69
    +    // Here we track changes in active window / application,
    
    70
    +    // by filtering focus events and window closures.
    
    71
    +    const handleActivation = (win, activation) => {
    
    72
    +      if (activation) {
    
    73
    +        if (!this._globalActivation) {
    
    74
    +          // focus changed within this window, bail out.
    
    75
    +          return;
    
    76
    +        }
    
    77
    +        this._globalActivation = false;
    
    78
    +      } else if (!Services.focus.activeWindow) {
    
    79
    +        // focus is leaving this window:
    
    80
    +        // let's track whether it remains within the browser.
    
    81
    +        lazy.setTimeout(() => {
    
    82
    +          this._globalActivation = !Services.focus.activeWindow;
    
    83
    +        }, 100);
    
    84
    +      }
    
    85
    +
    
    86
    +      const checkClipboardContent = () => {
    
    87
    +        const clipboardHash = this._computeClipboardHash();
    
    88
    +        if (clipboardHash !== this._lastClipboardHash) {
    
    89
    +          this._isPrivateClipboard =
    
    90
    +            !activation &&
    
    91
    +            (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing ||
    
    92
    +              lazy.PrivateBrowsingUtils.isWindowPrivate(win));
    
    93
    +          this._lastClipboardHash = clipboardHash;
    
    94
    +          this._log.debug(
    
    95
    +            `Clipboard changed: private ${this._isPrivateClipboard}, hash ${clipboardHash}.`
    
    96
    +          );
    
    97
    +        }
    
    98
    +      };
    
    99
    +
    
    100
    +      if (win.closed) {
    
    101
    +        checkClipboardContent();
    
    102
    +      } else {
    
    103
    +        // defer clipboard access on DOM events to work-around tor-browser#42306
    
    104
    +        lazy.setTimeout(checkClipboardContent, 0);
    
    105
    +      }
    
    106
    +    };
    
    107
    +    const focusListener = e =>
    
    108
    +      e.isTrusted && handleActivation(e.currentTarget, e.type === "focusin");
    
    109
    +    const initWindow = win => {
    
    110
    +      for (const e of ["focusin", "focusout"]) {
    
    111
    +        win.addEventListener(e, focusListener);
    
    112
    +      }
    
    113
    +    };
    
    114
    +    for (const w of Services.ww.getWindowEnumerator()) {
    
    115
    +      initWindow(w);
    
    116
    +    }
    
    117
    +    Services.ww.registerNotification((win, event) => {
    
    118
    +      switch (event) {
    
    119
    +        case "domwindowopened":
    
    120
    +          initWindow(win);
    
    121
    +          break;
    
    122
    +        case "domwindowclosed":
    
    123
    +          handleActivation(win, false);
    
    124
    +          if (
    
    125
    +            this._isPrivateClipboard &&
    
    126
    +            lazy.PrivateBrowsingUtils.isWindowPrivate(win) &&
    
    127
    +            (this._shuttingDown ||
    
    128
    +              !Array.from(Services.ww.getWindowEnumerator()).find(
    
    129
    +                w =>
    
    130
    +                  lazy.PrivateBrowsingUtils.isWindowPrivate(w) &&
    
    131
    +                  // We need to filter out the HIDDEN WebExtensions window,
    
    132
    +                  // which might be private as well but is not UI-relevant.
    
    133
    +                  !w.location.href.startsWith("chrome://extensions/")
    
    134
    +              ))
    
    135
    +          ) {
    
    136
    +            // no more private windows, empty private content if needed
    
    137
    +            this.emptyPrivate();
    
    138
    +          }
    
    139
    +      }
    
    140
    +    });
    
    141
    +
    
    142
    +    lazy.AsyncShutdown.quitApplicationGranted.addBlocker(
    
    143
    +      "ClipboardPrivacy: removing private data",
    
    144
    +      () => {
    
    145
    +        this._shuttingDown = true;
    
    146
    +        this.emptyPrivate();
    
    147
    +      }
    
    148
    +    );
    
    149
    +  },
    
    150
    +  emptyPrivate() {
    
    151
    +    if (
    
    152
    +      this._isPrivateClipboard &&
    
    153
    +      !Services.prefs.getBoolPref(
    
    154
    +        "browser.privatebrowsing.preserveClipboard",
    
    155
    +        false
    
    156
    +      ) &&
    
    157
    +      this._lastClipboardHash === this._computeClipboardHash()
    
    158
    +    ) {
    
    159
    +      // nsIClipboard.emptyClipboard() does nothing in Wayland:
    
    160
    +      // we'll set an empty string as a work-around.
    
    161
    +      const trans = this._createTransferable();
    
    162
    +      const flavor = "text/plain";
    
    163
    +      trans.addDataFlavor(flavor);
    
    164
    +      const emptyString = Cc["@mozilla.org/supports-string;1"].createInstance(
    
    165
    +        Ci.nsISupportsString
    
    166
    +      );
    
    167
    +      emptyString.data = "";
    
    168
    +      trans.setTransferData(flavor, emptyString);
    
    169
    +      const { clipboard } = Services,
    
    170
    +        { kGlobalClipboard } = clipboard;
    
    171
    +      clipboard.setData(trans, null, kGlobalClipboard);
    
    172
    +      clipboard.emptyClipboard(kGlobalClipboard);
    
    173
    +      this._lastClipboardHash = null;
    
    174
    +      this._isPrivateClipboard = false;
    
    175
    +      this._log.info("Private clipboard emptied.");
    
    176
    +    }
    
    177
    +  },
    
    178
    +};

  • browser/modules/moz.build
    ... ... @@ -136,7 +136,6 @@ EXTRA_JS_MODULES += [
    136 136
         "PopupBlockerObserver.sys.mjs",
    
    137 137
         "ProcessHangMonitor.sys.mjs",
    
    138 138
         "Sanitizer.sys.mjs",
    
    139
    -    "SecurityLevelRestartNotification.sys.mjs",
    
    140 139
         "SelectionChangedMenulist.sys.mjs",
    
    141 140
         "SharingUtils.sys.mjs",
    
    142 141
         "SiteDataManager.sys.mjs",
    
    ... ... @@ -149,6 +148,8 @@ EXTRA_JS_MODULES += [
    149 148
     
    
    150 149
     MOZ_SRC_FILES += [
    
    151 150
         "ContextId.sys.mjs",
    
    151
    +    "ClipboardPrivacy.sys.mjs",
    
    152
    +    "SecurityLevelRestartNotification.sys.mjs",
    
    152 153
     ]
    
    153 154
     
    
    154 155
     if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":