/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // Test that (real) files can be pasted into chrome/content. // Pasting files should also hide all other data from content. function setClipboard(path) { const file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); file.initWithPath(path); const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance( Ci.nsITransferable ); trans.init(null); trans.addDataFlavor("application/x-moz-file"); trans.setTransferData("application/x-moz-file", file); trans.addDataFlavor("text/plain"); const str = Cc["@mozilla.org/supports-string;1"].createInstance( Ci.nsISupportsString ); str.data = "Alternate"; trans.setTransferData("text/plain", str); // Write to clipboard. Services.clipboard.setData(trans, null, Ci.nsIClipboard.kGlobalClipboard); } add_task(async function () { await SpecialPowers.pushPrefEnv({ set: [["dom.events.dataTransfer.mozFile.enabled", true]], }); // Create a temporary file that will be pasted. const file = await IOUtils.createUniqueFile( PathUtils.tempDir, "test-file.txt", 0o600 ); await IOUtils.writeUTF8(file, "Hello World!"); // Put the data directly onto the native clipboard to make sure // it isn't handled internally in Gecko somehow. setClipboard(file); let tab = await BrowserTestUtils.openNewForegroundTab( gBrowser, "https://example.com/browser/browser/base/content/test/general/clipboard_pastefile.html" ); let browser = tab.linkedBrowser; let resultPromise = SpecialPowers.spawn(browser, [], function (arg) { return new Promise(resolve => { content.document.addEventListener("testresult", event => { resolve(event.detail.result); }); }); }); // Focus in content await SpecialPowers.spawn(browser, [], async function () { content.document.getElementById("input").focus(); }); // Paste file into in content await BrowserTestUtils.synthesizeKey("v", { accelKey: true }, browser); let result = await resultPromise; is(result, PathUtils.filename(file), "Correctly pasted file in content"); var input = document.createElement("input"); document.documentElement.appendChild(input); input.focus(); await new Promise((resolve, reject) => { input.addEventListener( "paste", function (event) { let dt = event.clipboardData; is(dt.types.length, 3, "number of types"); ok(dt.types.includes("text/plain"), "text/plain exists in types"); ok( dt.types.includes("application/x-moz-file"), "application/x-moz-file exists in types" ); is(dt.types[2], "Files", "Last type should be 'Files'"); ok( dt.mozTypesAt(0).contains("text/plain"), "text/plain exists in mozTypesAt" ); is( dt.getData("text/plain"), "Alternate", "text/plain returned in getData" ); is( dt.mozGetDataAt("text/plain", 0), "Alternate", "text/plain returned in mozGetDataAt" ); ok( dt.mozTypesAt(0).contains("application/x-moz-file"), "application/x-moz-file exists in mozTypesAt" ); let mozFile = dt.mozGetDataAt("application/x-moz-file", 0); ok( mozFile instanceof Ci.nsIFile, "application/x-moz-file returned nsIFile with mozGetDataAt" ); is( mozFile.leafName, PathUtils.filename(file), "nsIFile has correct leafName" ); resolve(); }, { capture: true, once: true } ); EventUtils.synthesizeKey("v", { accelKey: true }); }); input.remove(); BrowserTestUtils.removeTab(tab); await IOUtils.remove(file); });