2 <?xml-stylesheet type=
"text/css" href=
"chrome://global/skin"?>
3 <?xml-stylesheet type=
"text/css" href=
"chrome://mochikit/content/tests/SimpleTest/test.css"?>
4 <window title=
"nsTransferable with large string"
5 xmlns=
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
7 <title>nsTransferable with large string
</title>
8 <script src=
"chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
10 <script type=
"application/javascript">
12 // This value is chosen such that the size of the memory for the string exceeds
13 // the kLargeDatasetSize threshold in nsTransferable.h (one million).
14 // Each character of a JS string is internally represented by two bytes,
15 // so the following string of length
500 001 uses
1 000 002 bytes.
16 const BIG_STRING =
"x" +
"BIGGY".repeat(
100000);
18 // Some value with a length that is exactly kLargeDatasetSize (
1 000 000).
19 const SMALL_STRING =
"small".repeat(
100000);
21 const nsTransferable = Components.Constructor(
"@mozilla.org/widget/transferable;1",
"nsITransferable");
22 const nsSupportsString = Components.Constructor(
"@mozilla.org/supports-string;1",
"nsISupportsString");
24 function assignTextToTransferable(transferable, string) {
25 var Suppstr = nsSupportsString();
26 Suppstr.data = string;
27 transferable.setTransferData(
"text/plain", Suppstr);
30 function checkTransferableText(transferable, expectedString, description) {
32 transferable.getTransferData(
"text/plain", data);
33 var actualValue = data.value.QueryInterface(Ci.nsISupportsString).data;
34 // Use ok + shortenString instead of is(...) to avoid dumping millions of characters in the output.
35 ok(actualValue === expectedString, description +
": text should match. " +
36 "Expected " + shortenString(expectedString) +
", got " + shortenString(actualValue));
38 function shortenString(str) {
39 return str && str.length
> 30 ? str.slice(
0,
10) +
"..." + str.slice(-
10) : String(str);
43 function isFDCountingSupported() {
44 // On on-Windows we can count the number of file handles for the current process,
45 // while on Windows we need to count the number of files in ${TempD}\mozilla-temp-files\,
46 // which can be unreliable, especially because nsAnonymousTemporaryFile has documented
47 // that the deletion might not be immediate.
49 // To avoid intermittents, we only check the file descriptor counts on non-Windows.
50 // test_bug1123480.xhtml will do some basic testing for Windows.
51 const {AppConstants} = ChromeUtils.importESModule(
52 "resource://gre/modules/AppConstants.sys.mjs"
54 return AppConstants.platform !== 'win';
57 function getClipboardCacheFDCount() {
58 var dir = Cc[
"@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
59 dir.initWithPath(
"/dev/fd");
61 for (var de = dir.directoryEntries; de.hasMoreElements(); ) {
62 var fdFile = de.nextFile;
65 fileSize = fdFile.fileSize;
67 // This can happen on macOS.
70 if (fileSize === BIG_STRING.length *
2 ||
71 // We are not expecting files of this small size,
72 // but include them in the count anyway
73 // in case the files are unexpectedly created.
74 fileSize === SMALL_STRING.length *
2) {
75 // Assume that the file was created by us if the size matches.
83 const {PrivateBrowsingUtils} = ChromeUtils.importESModule(
84 "resource://gre/modules/PrivateBrowsingUtils.sys.mjs"
87 var win = window.browsingContext.topChromeWindow.open(
"about:blank",
"_blank",
"chrome, width=500, height=200");
88 ok(win,
"should open window");
89 is(PrivateBrowsingUtils.isContentWindowPrivate(win), false,
"used correct window context");
91 // ### Part
1 - Writing to the clipboard.
93 var Loadctx = PrivateBrowsingUtils.privacyContextFromWindow(win);
94 var Transfer = nsTransferable();
95 Transfer.init(Loadctx);
96 Transfer.addDataFlavor(
"text/plain");
97 var initialFdCount = isFDCountingSupported() ? getClipboardCacheFDCount() : -
1;
99 assignTextToTransferable(Transfer, BIG_STRING);
100 checkTransferableText(Transfer, BIG_STRING,
"transferable after assigning BIG_STRING");
101 if (isFDCountingSupported()) {
102 is(getClipboardCacheFDCount(), initialFdCount +
1,
"should use a file for BIG_STRING");
105 // Share the transferable with the system.
106 Services.clipboard.setData(Transfer, null, Services.clipboard.kGlobalClipboard);
108 // Sanity check: Copying to the clipboard should not have altered the transferable.
109 checkTransferableText(Transfer, BIG_STRING,
"transferable after copying to clipboard");
110 if (isFDCountingSupported()) {
111 // We are only counting file descriptors for the current process,
112 // so even if the test were to be multi-process and the parent process creates another
113 // nsTransferable, then the count should still be the same.
114 is(getClipboardCacheFDCount(), initialFdCount +
1,
"should still be using files for previously stored BIG_STRING");
116 // Re-establish baseline for the second part of the test below.
117 initialFdCount = getClipboardCacheFDCount();
120 // ### Part
2 - Reading from the clipboard.
122 var Transfer2 = nsTransferable();
123 Transfer2.init(Loadctx);
124 Transfer2.addDataFlavor(
"text/plain");
126 // Iniitalize with a small string, so we can see that mData -
> mCacheFD works.
127 assignTextToTransferable(Transfer2, SMALL_STRING);
128 checkTransferableText(Transfer2, SMALL_STRING,
"transferable after assigning SMALL_STRING");
129 if (isFDCountingSupported()) {
130 is(getClipboardCacheFDCount(), initialFdCount,
"should not use file to store SMALL_STRING.");
133 // Check whether the clipboard data can be read, and simulatenously trigger mData -
> mCacheFD.
134 Services.clipboard.getData(Transfer2, Services.clipboard.kGlobalClipboard, SpecialPowers.wrap(window).browsingContext.currentWindowContext);
135 checkTransferableText(Transfer2, BIG_STRING,
"transferable after retrieving from clipboard");
136 if (isFDCountingSupported()) {
137 is(getClipboardCacheFDCount(), initialFdCount +
1,
"should use a file for BIG_STRING (read from clipboard).");
140 // Store a small string, to exercise the code path from mCacheFD -
> mData.
141 assignTextToTransferable(Transfer2, SMALL_STRING);
142 checkTransferableText(Transfer2, SMALL_STRING,
"transferable after assigning SMALL_STRING");
143 if (isFDCountingSupported()) {
144 is(getClipboardCacheFDCount(), initialFdCount,
"should release the file after clearing the transferable.");
150 <!-- test results are displayed in the html:body -->
151 <body xmlns=
"http://www.w3.org/1999/xhtml">
152 This test checks whether a big string can be copied to the clipboard, and then retrieved in the same form.
153 On non-Windows, the test also checks whether the data of the transferable is really stored in a file.