Files
sousa-gecko/widget/tests/browser/browser_test_clipboardcache.js
T
Emilio Cobos Álvarez feede7eb94 Bug 2033191 - Remove all non-node ownerGlobal usage. r=firefox-desktop-core-reviewers ,extension-reviewers,credential-management-reviewers,devtools-reviewers,fxview-reviewers,tabbrowser-reviewers,omc-reviewers,migration-reviewers,webcompat-reviewers,urlbar-reviewers,whimboo,akulyk,twisniewski,dao,robwu,mconley,sachung,sfoster,dimi,nchevobbe
This is written by greening up the tree with the following patch:

  https://hg.mozilla.org/try/rev/4f0388e9b8f76ff3008d3ec74ee793bb8f9fc364

All uses are effectively one of these categories:

 * windowRoot.ownerGlobal usage. Replaced by an explicit .window
   property.
 * Things that accidentally were given a window when they expected an
   element. Fixed by fixing callers as appropriate. Examples of these
   are using isBrowserPrivate(window) or so, or various test methods
   that expect a <browser> or <tabbrowser> and were given a Window.
 * Things that had a window-or-node and used ownerGlobal to normalize to
   a window. E.g. the AutoScrollChild or extensions code. Fixed by
   checking explicitly for Window.
 * Things that had a window and called ownerGlobal on it. Fixed by just
   removing the ownerGlobal accessor.

Main idea after this is to replace all .ownerGlobal usage with
.documentGlobal, and remove .ownerGlobal from JS (maybe exposing
.relevantGlobal if absolutely needed).

Differential Revision: https://phabricator.services.mozilla.com/D295189
2026-04-29 05:04:36 +00:00

146 lines
5.2 KiB
JavaScript

"use strict";
requestLongerTimeout(2);
// Note: widget/tests/test_bug1123480.xhtml checks whether nsTransferable behaves
// as expected with regards to private browsing mode and the clipboard cache,
// i.e. that the clipboard is not cached to the disk when private browsing mode
// is enabled.
//
// This test tests that the clipboard is not cached to the disk by IPC,
// as a regression test for bug 1396224.
// It indirectly uses nsTransferable, via the async navigator.clipboard API.
// Create over 1 MB of sample garbage text. JavaScript strings are represented
// by UTF16 strings, so the size is twice as much as the actual string length.
// This value is chosen such that the size of the memory for the string exceeds
// the kLargeDatasetSize threshold in nsTransferable.h.
// It is also not a round number to reduce the odds of having an accidental
// collisions with another file (since the test below looks at the file size
// to identify the file).
var Ipsum = "0123456789".repeat(1234321);
var IpsumByteLength = Ipsum.length * 2;
var SHORT_STRING_NO_CACHE = "short string that will not be cached to the disk";
// Get a list of open file descriptors that refer to a file with the same size
// as the expected data (and assume that any mutations in file descriptor counts
// are caused by our test).
// TODO: This logic only counts file descriptors that are still open (e.g. when
// data persists after a copy). It does not detect cache files that exist only
// temporarily (e.g. after a paste).
function getClipboardCacheFDCount() {
let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
if (AppConstants.platform === "win") {
// On Windows, nsAnonymousTemporaryFile does not immediately delete a file.
// Instead, the Windows-specific FILE_FLAG_DELETE_ON_CLOSE flag is used,
// which means that the file is deleted when the last handle is closed.
// Apparently, this flag is unreliable (e.g. when the application crashes),
// so nsAnonymousTemporaryFile stores the temporary files in a subdirectory,
// which is cleaned up some time after start-up.
// This is just a test, and during the test we deterministically close the
// handles, so if FILE_FLAG_DELETE_ON_CLOSE does the thing it promises, the
// file is actually removed when the handle is closed.
// Path from nsAnonymousTemporaryFile.cpp, GetTempDir.
dir.initWithPath(PathUtils.join(PathUtils.tempDir, "mozilla-temp-files"));
} else {
dir.initWithPath("/dev/fd");
}
let count = 0;
for (let fdFile of dir.directoryEntries) {
let fileSize;
try {
fileSize = fdFile.fileSize;
} catch (e) {
// This can happen on macOS.
continue;
}
if (fileSize === IpsumByteLength) {
// Assume that the file was created by us if the size matches.
++count;
}
}
return count;
}
async function testCopyPaste(isPrivate) {
let win = await BrowserTestUtils.openNewBrowserWindow({ private: isPrivate });
let tab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser);
let browser = tab.linkedBrowser;
// Sanitize environment
await SpecialPowers.spawn(
browser,
[SHORT_STRING_NO_CACHE],
async shortStr => {
await content.navigator.clipboard.writeText(shortStr);
}
);
let initialFdCount = getClipboardCacheFDCount();
await SpecialPowers.spawn(browser, [Ipsum], async largeString => {
await content.navigator.clipboard.writeText(largeString);
});
let fdCountAfterCopy = getClipboardCacheFDCount();
if (isPrivate) {
is(fdCountAfterCopy, initialFdCount, "Private write");
} else {
is(fdCountAfterCopy, initialFdCount + 1, "Cached write");
}
let readStr = await SpecialPowers.spawn(browser, [], async () => {
let { document } = content;
document.body.contentEditable = true;
document.body.focus();
let pastePromise = new Promise(resolve => {
document.addEventListener(
"paste",
e => {
resolve(e.clipboardData.getData("text/plain"));
},
{ once: true }
);
});
document.execCommand("paste");
return pastePromise;
});
// Don't use Assert.strictEqual here because the test starts timing out,
// because the logging creates lots of copies of this very huge string.
// eslint-disable-next-line mozilla/no-comparison-or-assignment-inside-ok
ok(readStr === Ipsum, "Read what we pasted");
if (isPrivate) {
is(getClipboardCacheFDCount(), fdCountAfterCopy, "Private read");
} else {
// Upon reading from the clipboard, a temporary nsTransferable is used, for
// which the cache is disabled. The content process does not cache clipboard
// data either. So the file descriptor count should be identical.
is(getClipboardCacheFDCount(), fdCountAfterCopy, "Read not cached");
}
// Cleanup.
await SpecialPowers.spawn(
browser,
[SHORT_STRING_NO_CACHE],
async shortStr => {
await content.navigator.clipboard.writeText(shortStr);
}
);
is(getClipboardCacheFDCount(), initialFdCount, "Drop clipboard cache if any");
BrowserTestUtils.removeTab(tab);
await BrowserTestUtils.closeWindow(win);
}
add_task(async function test_private() {
await testCopyPaste(true);
});
add_task(async function test_non_private() {
await testCopyPaste(false);
});