Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
-->
<window title="Mozilla Bug 1123480"
onload="RunTest();">
<title>nsTransferable PBM Overflow Selection Test</title>
<script type="application/javascript">
<![CDATA[
// 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 never be cached to the disk";
function isWindows() {
const {AppConstants} = ChromeUtils.importESModule(
"resource://gre/modules/AppConstants.sys.mjs"
);
return AppConstants.platform === 'win';
}
// 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).
function getClipboardCacheFDCount() {
var dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
if (isWindows()) {
// On Windows, nsAnonymousTemporaryFile does not immediately delete the 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");
}
var count = 0;
for (var de = dir.directoryEntries; de.hasMoreElements(); ) {
var fdFile = de.nextFile;
var 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 RunTest() {
SimpleTest.waitForExplicitFinish();
const gClipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
// Sanitize environment
gClipboardHelper.copyString(SHORT_STRING_NO_CACHE);
await new Promise(resolve => setTimeout(resolve, 0));
var initialFdCount = getClipboardCacheFDCount();
// Overflow a nsTransferable region by using the clipboard helper
gClipboardHelper.copyString(Ipsum);
// gClipboardHelper.copyString also puts the data on the selection
// clipboard if the platform supports it.
var expectedFdDelta = Services.clipboard.isClipboardTypeSupported(Services.clipboard.kSelectionClipboard) ? 2 : 1;
// Undefined private browsing mode should cache to disk
is(getClipboardCacheFDCount(), initialFdCount + expectedFdDelta, "should cache to disk when PBM is undefined");
// Sanitize environment again.
gClipboardHelper.copyString(SHORT_STRING_NO_CACHE);
await new Promise(resolve => setTimeout(resolve, 0));
is(getClipboardCacheFDCount(), initialFdCount, "should have cleared the clipboard data");
// Repeat procedure of plain text selection with private browsing
// disabled and enabled
const {PrivateBrowsingUtils} = ChromeUtils.importESModule(
"resource://gre/modules/PrivateBrowsingUtils.sys.mjs"
);
for (let private of [false, true]) {
var win = window.browsingContext.topChromeWindow.open("about:blank", "_blank", "chrome, width=500, height=200" + (private ? ", private" : ""));
ok(win, private ? "should open private window" : "should open non-private window");
is(PrivateBrowsingUtils.isContentWindowPrivate(win), private, "used correct window context");
// Select plaintext in private/non-private channel
const nsTransferable = Components.Constructor("@mozilla.org/widget/transferable;1", "nsITransferable");
const nsSupportsString = Components.Constructor("@mozilla.org/supports-string;1", "nsISupportsString");
var Loadctx = PrivateBrowsingUtils.privacyContextFromWindow(win);
var Transfer = nsTransferable();
var Suppstr = nsSupportsString();
Suppstr.data = Ipsum;
Transfer.init(Loadctx);
Transfer.addDataFlavor("text/plain");
Transfer.setTransferData("text/plain", Suppstr);
// Enabled private browsing mode should not cache any selection to disk; disabled should
if (private) {
is(getClipboardCacheFDCount(), initialFdCount, "did not violate private browsing mode");
} else {
is(getClipboardCacheFDCount(), initialFdCount + 1, "should save memory by caching non-private clipboard data to disk");
}
// Share the transferable with the system.
Services.clipboard.setData(Transfer, null, Services.clipboard.kGlobalClipboard);
if (private) {
is(getClipboardCacheFDCount(), initialFdCount, "did not violate private browsing mode");
} else {
is(getClipboardCacheFDCount(), initialFdCount + 1, "should save memory by caching non-private clipboard data to disk");
}
// Sanitize the environment.
Suppstr = nsSupportsString();
Suppstr.data = SHORT_STRING_NO_CACHE;
Transfer.setTransferData("text/plain", Suppstr);
await new Promise(resolve => setTimeout(resolve, 0));
is(getClipboardCacheFDCount(), initialFdCount, "should drop the cache file, if any.");
Services.clipboard.setData(Transfer, null, Services.clipboard.kGlobalClipboard);
is(getClipboardCacheFDCount(), initialFdCount, "should postsanitize the environment");
}
SimpleTest.finish();
}
]]>
</script>
<!-- test results are displayed in the html:body -->
target="_blank">Mozilla Bug 1123480</a>
</body>
</window>