[tbb-commits] [Git][tpo/applications/tor-browser][tor-browser-115.4.0esr-13.5-1] fixup! Bug 42019: Empty browser's clipboard on browser shutdown

richard (@richard) git at gitlab.torproject.org
Wed Oct 18 21:22:24 UTC 2023



richard pushed to branch tor-browser-115.4.0esr-13.5-1 at The Tor Project / Applications / Tor Browser


Commits:
ef3a546d by hackademix at 2023-10-18T21:46:03+02:00
fixup! Bug 42019: Empty browser's clipboard on browser shutdown

Bug 42154: empty clipboard content from private windows on exit.

- - - - -


2 changed files:

- browser/app/profile/001-base-profile.js
- browser/components/BrowserGlue.sys.mjs


Changes:

=====================================
browser/app/profile/001-base-profile.js
=====================================
@@ -87,6 +87,9 @@ pref("browser.sessionstore.resume_from_crash", false);
 // Also not needed in PBM at the moment.
 pref("browser.pagethumbnails.capturing_disabled", true);
 
+// Empty clipboard content from private windows on exit (tor-browser#42154)
+pref("browser.privatebrowsing.preserveClipboard", false);
+
 // Enable HTTPS-Only mode (tor-browser#19850)
 pref("dom.security.https_only_mode", true);
 // The previous pref automatically sets this to true (see StaticPrefList.yaml),


=====================================
browser/components/BrowserGlue.sys.mjs
=====================================
@@ -150,6 +150,119 @@ const PRIVATE_BROWSING_EXE_ICON_INDEX = 1;
 const PREF_PRIVATE_BROWSING_SHORTCUT_CREATED =
   "browser.privacySegmentation.createdShortcut";
 
+// Empty clipboard content from private windows on exit
+// (tor-browser#42154)
+const ClipboardPrivacy = {
+  _lastClipboardHash: null,
+  _globalActivation: false,
+  _isPrivateClipboard: false,
+  _hasher: null,
+
+  _computeClipboardHash(win = Services.ww.activeWindow) {
+    const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
+      Ci.nsITransferable
+    );
+    trans.init(win?.docShell?.QueryInterface(Ci.nsILoadContext) || null);
+    ["text/x-moz-url", "text/plain"].forEach(trans.addDataFlavor);
+    try {
+      Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
+      const clipboardContent = {};
+      trans.getAnyTransferData({}, clipboardContent);
+      const { data } = clipboardContent.value.QueryInterface(
+        Ci.nsISupportsString
+      );
+      const bytes = new TextEncoder().encode(data);
+      const hasher = (this._hasher ||= Cc[
+        "@mozilla.org/security/hash;1"
+      ].createInstance(Ci.nsICryptoHash));
+      hasher.init(hasher.SHA256);
+      hasher.update(bytes, bytes.length);
+      return hasher.finish(true);
+    } catch (e) {}
+    return null;
+  },
+
+  startup() {
+    this._lastClipboardHash = this._computeClipboardHash();
+
+    // Here we track changes in active window / application,
+    // by filtering focus events and window closures.
+    const handleActivation = (win, activation) => {
+      if (activation) {
+        if (!this._globalActivation) {
+          // focus changed within this window, bail out.
+          return;
+        }
+        this._globalActivation = false;
+      } else if (!Services.focus.activeWindow) {
+        // focus is leaving this window:
+        // let's track whether it remains within the browser.
+        lazy.setTimeout(() => {
+          this._globalActivation = !Services.focus.activeWindow;
+        }, 100);
+      }
+      const clipboardHash = this._computeClipboardHash(win);
+      if (clipboardHash !== this._lastClipboardHash) {
+        this._isPrivateClipboard =
+          !activation &&
+          (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing ||
+            lazy.PrivateBrowsingUtils.isWindowPrivate(win));
+        this._lastClipboardHash = clipboardHash;
+        console.log(
+          `Clipboard changed: private ${this._isPrivateClipboard}, hash ${clipboardHash}.`
+        );
+      }
+    };
+    const focusListener = e =>
+      e.isTrusted && handleActivation(e.currentTarget, e.type === "focusin");
+    const initWindow = win => {
+      for (const e of ["focusin", "focusout"]) {
+        win.addEventListener(e, focusListener);
+      }
+    };
+    for (const w of Services.ww.getWindowEnumerator()) {
+      initWindow(w);
+    }
+    Services.ww.registerNotification((win, event) => {
+      switch (event) {
+        case "domwindowopened":
+          initWindow(win);
+          break;
+        case "domwindowclosed":
+          handleActivation(win, false);
+          if (
+            this._isPrivateClipboard &&
+            lazy.PrivateBrowsingUtils.isWindowPrivate(win) &&
+            !(
+              lazy.PrivateBrowsingUtils.permanentPrivateBrowsing ||
+              Array.from(Services.ww.getWindowEnumerator()).find(w =>
+                lazy.PrivateBrowsingUtils.isWindowPrivate(w)
+              )
+            )
+          ) {
+            // no more private windows, empty private content if needed
+            this.emptyPrivate();
+          }
+      }
+    });
+  },
+  emptyPrivate() {
+    if (
+      this._isPrivateClipboard &&
+      !Services.prefs.getBoolPref(
+        "browser.privatebrowsing.preserveClipboard",
+        false
+      ) &&
+      this._lastClipboardHash === this._computeClipboardHash()
+    ) {
+      Services.clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard);
+      this._lastClipboardHash = null;
+      this._isPrivateClipboard = false;
+      console.log("Private clipboard emptied.");
+    }
+  },
+};
+
 /**
  * Fission-compatible JSProcess implementations.
  * Each actor options object takes the form of a ProcessActorOptions dictionary.
@@ -1753,6 +1866,8 @@ BrowserGlue.prototype = {
 
     lazy.TorProviderBuilder.firstWindowLoaded();
 
+    ClipboardPrivacy.startup();
+
     this._firstWindowTelemetry(aWindow);
     this._firstWindowLoaded();
 
@@ -2013,7 +2128,7 @@ BrowserGlue.prototype = {
           lazy.UpdateListener.reset();
         }
       },
-      () => Services.clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard), // tor-browser#42019
+      () => ClipboardPrivacy.emptyPrivate(), // tor-browser#42019
       () => lazy.OnionAliasStore.uninit(),
     ];
 



View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/ef3a546d3ebdfbf058c66483000fe9c4a65adeac

-- 
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/ef3a546d3ebdfbf058c66483000fe9c4a65adeac
You're receiving this email because of your account on gitlab.torproject.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.torproject.org/pipermail/tbb-commits/attachments/20231018/02fe3ca3/attachment-0001.htm>


More information about the tbb-commits mailing list