--- a/dom/base/test/test_bug574596.html
+++ b/dom/base/test/test_bug574596.html
@@ -37,16 +37,17 @@ var dragLinkText = [[
{ type:"text/_moz_htmlcontext", data:"", eqTest:ignoreFunc },
{ type:"text/_moz_htmlinfo", data:"", eqTest:ignoreFunc },
{ type:"text/html", data:'<div id="link1"><a href="http://www.mozilla.org/">link1</a></div>' },
{ type:"text/plain", data:"http://www.mozilla.org/" }
]];
function dumpTransfer(dataTransfer,expect) {
+ dataTransfer = SpecialPowers.wrap(dataTransfer);
dtData = dataTransfer.mozItemCount + "items:\n";
for (var i = 0; i < dataTransfer.mozItemCount; i++) {
var dtTypes = dataTransfer.mozTypesAt(i);
for (var j = 0; j < dtTypes.length; j++) {
var actualData = dataTransfer.mozGetDataAt(dtTypes[j],i)
if (expect && expect[i] && expect[i][j]) {
if (expect[i][j].eqTest)
dtData += expect[i][j].eqTest(actualData,expect[i][j].data) ? "ok" : "fail";
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -35,16 +35,18 @@
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/FileList.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/OSFileSystem.h"
#include "mozilla/dom/Promise.h"
#include "nsNetUtil.h"
+#define MOZ_CALLS_ENABLED_PREF "dom.datatransfer.mozAtAPIs"
+
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(DataTransfer)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DataTransfer)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mItems)
@@ -1518,10 +1520,27 @@ DataTransfer::SetMode(DataTransfer::Mode
{
if (!PrefProtected() && aMode == Mode::Protected) {
mMode = Mode::ReadOnly;
} else {
mMode = aMode;
}
}
+/* static */
+bool
+DataTransfer::MozAtAPIsEnabled(JSContext* aCx, JSObject* aObj /*unused*/)
+{
+ // Read the pref
+ static bool sPrefCached = false;
+ static bool sPrefCacheValue = false;
+
+ if (!sPrefCached) {
+ sPrefCached = true;
+ Preferences::AddBoolVarCache(&sPrefCacheValue, MOZ_CALLS_ENABLED_PREF);
+ }
+
+ // We can expose moz* APIs if we are chrome code or if pref is enabled
+ return nsContentUtils::IsSystemCaller(aCx) || sPrefCacheValue;
+}
+
} // namespace dom
} // namespace mozilla
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -423,16 +423,21 @@ public:
//
// If kFileMime is supported, then it will be placed either at
// index 0 or at index 1 in aResult
static void
GetExternalClipboardFormats(const int32_t& aWhichClipboard,
const bool& aPlainTextOnly,
nsTArray<nsCString>* aResult);
+ // Returns true if moz* APIs should be exposed (true for chrome code or if
+ // dom.datatransfer.moz pref is enabled).
+ // The affected moz* APIs are mozItemCount, mozTypesAt, mozClearDataAt, mozSetDataAt, mozGetDataAt
+ static bool MozAtAPIsEnabled(JSContext* cx, JSObject* obj);
+
protected:
// caches text and uri-list data formats that exist in the drag service or
// clipboard for retrieval later.
nsresult CacheExternalData(const char* aFormat, uint32_t aIndex,
nsIPrincipal* aPrincipal, bool aHidden);
// caches the formats that exist in the drag service that were added by an
--- a/dom/events/test/test_DataTransferItemList.html
+++ b/dom/events/test/test_DataTransferItemList.html
@@ -1,21 +1,21 @@
<html>
<head>
- <title>Tests for the DatTransferItemList object</title>
+ <title>Tests for the DataTransferItemList object</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/AddTask.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body style="height: 300px; overflow: auto;">
<p id="display"> </p>
<img id="image" draggable="true" src="data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%18%00%00%00%18%02%03%00%00%00%9D%19%D5k%00%00%00%04gAMA%00%00%B1%8F%0B%FCa%05%00%00%00%0CPLTE%FF%FF%FF%FF%FF%FF%F7%DC%13%00%00%00%03%80%01X%00%00%00%01tRNS%08N%3DPT%00%00%00%01bKGD%00%88%05%1DH%00%00%00%09pHYs%00%00%0B%11%00%00%0B%11%01%7Fd_%91%00%00%00%07tIME%07%D2%05%0C%14%0C%0D%D8%3F%1FQ%00%00%00%5CIDATx%9C%7D%8E%CB%09%C0%20%10D%07r%B7%20%2F%E9wV0%15h%EA%D9%12D4%BB%C1x%CC%5C%1E%0C%CC%07%C0%9C0%9Dd7()%C0A%D3%8D%E0%B8%10%1DiCHM%D0%AC%D2d%C3M%F1%B4%E7%FF%10%0BY%AC%25%93%CD%CBF%B5%B2%C0%3Alh%CD%AE%13%DF%A5%F7%E0%03byW%09A%B4%F3%E2%00%00%00%00IEND%AEB%60%82">
-<div id="over" "style="width: 100px; height: 100px; border: 2px black dashed;">
+<div id="over" style="width: 100px; height: 100px; border: 2px black dashed;">
drag over here
</div>
<script>
function spin() {
// Defer to the event loop twice to wait for any events to be flushed out.
return new Promise(function(a) {
SimpleTest.executeSoon(function() {
--- a/dom/events/test/test_bug1264380.html
+++ b/dom/events/test/test_bug1264380.html
@@ -25,17 +25,17 @@ function runTests()
target.href = "http://www.mozilla.org/";
shadow.appendChild(target);
let dataTransfer;
let trapDrag = function(event) {
ok(true, "Got dragstart event");
dataTransfer = event.dataTransfer;
ok(dataTransfer, "DataTransfer object is available.");
- is(dataTransfer.mozItemCount, 1, "initial link item count");
+ is(SpecialPowers.wrap(dataTransfer).mozItemCount, 1, "initial link item count");
is(dataTransfer.getData("text/uri-list"), "http://www.mozilla.org/", "link text/uri-list");
is(dataTransfer.getData("text/plain"), "http://www.mozilla.org/", "link text/plain");
}
ok(!dragService.getCurrentSession(), "There shouldn't be a drag session!");
iframeWin.addEventListener("dragstart", trapDrag, true);
synthesizeMouse(target, 2, 2, { type: "mousedown" }, iframeWin);
synthesizeMouse(target, 11, 11, { type: "mousemove" }, iframeWin);
--- a/dom/events/test/test_dragstart.html
+++ b/dom/events/test/test_dragstart.html
@@ -36,20 +36,16 @@ function afterDragTests()
// be read only.
ok(gDataTransfer instanceof DataTransfer, "DataTransfer after dragstart event");
checkTypes(gDataTransfer, [], 0, "after dragstart event");
expectError(() => gDataTransfer.setData("text/plain", "Some Text"),
"NoModificationAllowedError", "setData when read only");
expectError(() => gDataTransfer.clearData("text/plain"),
"NoModificationAllowedError", "clearData when read only");
- expectError(() => gDataTransfer.mozSetDataAt("text/plain", "Some Text", 0),
- "NoModificationAllowedError", "setDataAt when read only");
- expectError(() => gDataTransfer.mozClearDataAt("text/plain", 0),
- "NoModificationAllowedError", "clearDataAt when read only");
expectError(() => gDataTransfer.addElement(draggable),
"NoModificationAllowedError", "addElement when read only");
var evt = document.createEvent("dragevent");
ok(evt instanceof DragEvent, "synthetic dragevent class")
ok(evt instanceof MouseEvent, "synthetic event inherits from MouseEvent")
evt.initDragEvent("dragstart", true, true, window, 1, 40, 35, 20, 15,
false, true, false, false, 0, null, null);
@@ -125,33 +121,37 @@ function doDragStartSelection(event)
// text/unicode and Text are available for compatibility. They retrieve the
// text/plain data
is(dt.getData("text/unicode"), "This is a draggable bit of text.", "initial selection text/unicode");
is(dt.getData("Text"), "This is a draggable bit of text.", "initial selection Text");
is(dt.getData("TEXT"), "This is a draggable bit of text.", "initial selection TEXT");
is(dt.getData("text/UNICODE"), "This is a draggable bit of text.", "initial selection text/UNICODE");
- is(dt.mozItemCount, 1, "initial selection item count");
+ is(SpecialPowers.wrap(dt).mozItemCount, 1, "initial selection item count");
dt.clearData("text/plain");
dt.clearData("text/html");
dt.clearData("text/_moz_htmlinfo");
dt.clearData("text/_moz_htmlcontext");
test_DataTransfer(dt);
setTimeout(afterDragTests, 0);
}
function test_DataTransfer(dt)
{
- is(dt.mozItemCount, 0, "empty itemCount");
+ is(SpecialPowers.wrap(dt).mozItemCount, 0, "empty itemCount");
var types = dt.types;
ok(Array.isArray(types), "empty types is an Array");
+ // The above test fails if we have SpecialPowers.wrap(dt).types instead of dt.types
+ // because chrome consumers get the 'ReturnValueNeedsContainsHack'.
+ // So wrap with special powers after the test
+ dt = SpecialPowers.wrap(dt);
checkTypes(dt, [], 0, "empty");
is(dt.getData("text/plain"), "", "empty data is empty");
// calling setDataAt requires an index that is 0 <= index <= dt.itemCount
expectError(() => dt.mozSetDataAt("text/plain", "Some Text", 1),
"IndexSizeError", "setDataAt index too high");
is(dt.mozUserCancelled, false, "userCancelled");
@@ -311,30 +311,28 @@ function test_DataTransfer(dt)
checkOneDataItem(dt, ["text/plain", "text/html"],
["Changed Second Item", "<em>Second Item</em>"], 1, "changed with setData item at index 1");
dt.mozSetDataAt("application/-moz-node", "draggable", 2);
is(dt.mozItemCount, 3, "setDataAt node itemCount");
checkOneDataItem(dt, ["application/-moz-node"], ["draggable"], 2, "setDataAt node item at index 2");
// Try to add and then remove a non-string type to the DataTransfer and ensure
- // that the type appears in DataTransfer.types. These calls need to be called
- // with SpecialPowers.wrap(), as adding and removing non-string/file types to
- // DataTransfer is chrome-only.
+ // that the type appears in DataTransfer.types.
{
- SpecialPowers.wrap(dt).mozSetDataAt("application/-x-body", document.body, 0);
+ dt.mozSetDataAt("application/-x-body", document.body, 0);
let found = false;
for (let i = 0; i < dt.types.length; ++i) {
if (dt.types[i] == "application/-x-body") {
found = true;
break;
}
}
ok(found, "Data should appear in datatransfer.types despite having a non-string type");
- SpecialPowers.wrap(dt).mozClearDataAt("application/-x-body", 0);
+ dt.mozClearDataAt("application/-x-body", 0);
}
dt.mozClearDataAt("text/html", 1);
is(dt.mozItemCount, 3, "clearDataAt itemCount");
checkOneDataItem(dt, ["text/plain", "text/html"],
["First Item", "Changed with setData"], 0, "clearDataAt item at index 0");
checkOneDataItem(dt, ["text/plain"], ["Changed Second Item"], 1, "clearDataAt item at index 1");
@@ -414,48 +412,48 @@ function test_DataTransfer(dt)
}
function doDragStartLink(event)
{
var dt = event.dataTransfer;
checkTypes(dt, ["text/x-moz-url", "text/x-moz-url-data", "text/x-moz-url-desc", "text/uri-list",
"text/_moz_htmlcontext", "text/_moz_htmlinfo", "text/html", "text/plain"], 0, "initial link");
- is(dt.mozItemCount, 1, "initial link item count");
+ is(SpecialPowers.wrap(dt).mozItemCount, 1, "initial link item count");
is(dt.getData("text/uri-list"), "http://www.mozilla.org/", "link text/uri-list");
is(dt.getData("text/plain"), "http://www.mozilla.org/", "link text/plain");
event.preventDefault();
gExtraDragTests++;
}
function doDragStartImage(event)
{
var dataurl = $("image").src;
var dt = event.dataTransfer;
checkTypes(dt, ["text/x-moz-url", "text/x-moz-url-data", "text/x-moz-url-desc", "text/uri-list",
"text/_moz_htmlcontext", "text/_moz_htmlinfo", "text/html", "text/plain"], 0, "initial image");
- is(dt.mozItemCount, 1, "initial image item count");
+ is(SpecialPowers.wrap(dt).mozItemCount, 1, "initial image item count");
is(dt.getData("text/uri-list"), dataurl, "image text/uri-list");
is(dt.getData("text/plain"), dataurl, "image text/plain");
event.preventDefault();
gExtraDragTests++;
}
function doDragStartInput(event)
{
var dt = event.dataTransfer;
checkTypes(dt, ["text/plain"], 0, "initial input");
- is(dt.mozItemCount, 1, "initial input item count");
+ is(SpecialPowers.wrap(dt).mozItemCount, 1, "initial input item count");
// is(dt.getData("text/plain"), "Text", "input text/plain");
// event.preventDefault();
}
function doDragStartSynthetic(event)
{
is(event.type, "dragstart", "synthetic dragstart event type");
@@ -506,21 +504,22 @@ function doDragOverSynthetic(event)
// Uncomment next two lines once the todo instanceof above is fixed.
// dt.setData("text/plain", "Text");
// is(dt.getData("text/plain"), "Text", "synthetic dragover data is set after adding");
}
function onDragStartDraggable(event)
{
var dt = event.dataTransfer;
- ok(dt.mozItemCount == 0 && dt.types.length == 0 && event.originalTarget == gDragInfo.target, gDragInfo.testid);
+ ok(SpecialPowers.wrap(dt).mozItemCount == 0 && dt.types.length == 0 && event.originalTarget == gDragInfo.target, gDragInfo.testid);
gExtraDragTests++;
}
+// Expects dt wrapped in SpecialPowers
function checkOneDataItem(dt, expectedtypes, expecteddata, index, testid)
{
checkTypes(dt, expectedtypes, index, testid);
for (var f = 0; f < expectedtypes.length; f++) {
if (index == 0)
is(dt.getData(expectedtypes[f]), expecteddata[f], testid + " getData " + expectedtypes[f]);
is(dt.mozGetDataAt(expectedtypes[f], index), expecteddata[f] ? expecteddata[f] : null,
testid + " getDataAt " + expectedtypes[f]);
@@ -532,23 +531,24 @@ function checkTypes(dt, expectedtypes, i
if (index == 0) {
var types = dt.types;
is(types.length, expectedtypes.length, testid + " types length");
for (var f = 0; f < expectedtypes.length; f++) {
is(types[f], expectedtypes[f], testid + " " + types[f] + " check");
}
}
- types = dt.mozTypesAt(index);
+ types = SpecialPowers.wrap(dt).mozTypesAt(index);
is(types.length, expectedtypes.length, testid + " typesAt length");
for (var f = 0; f < expectedtypes.length; f++) {
is(types[f], expectedtypes[f], testid + " " + types[f] + " at " + index + " check");
}
}
+// Expects dt wrapped in SpecialPowers
function checkURL(dt, url, fullurllist, index, testid)
{
is(dt.getData("text/uri-list"), fullurllist, testid + " text/uri-list");
is(dt.getData("URL"), url, testid + " URL");
is(dt.mozGetDataAt("text/uri-list", 0), fullurllist, testid + " text/uri-list");
is(dt.mozGetDataAt("URL", 0), fullurllist, testid + " URL");
}
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -85,16 +85,17 @@ subsuite = clipboard
[test_bug1434273.html]
[test_clientRects.html]
[test_clipboard_disallowed.html]
[test_clipboard_events.html]
subsuite = clipboard
[test_consoleAPI.html]
[test_contentViewer_overrideDPPX.html]
[test_CCW_optimization.html]
+[test_datatransfer_disallowed.html]
[test_devicePixelRatio_with_zoom.html]
[test_DOMMatrix.html]
[test_domWindowUtils.html]
[test_domWindowUtils_scrollbarSize.html]
[test_domWindowUtils_scrollXY.html]
[test_donottrack.html]
[test_focus_scrollchildframe.html]
[test_focus_legend_noparent.html]
--- a/dom/tests/mochitest/general/test_clipboard_disallowed.html
+++ b/dom/tests/mochitest/general/test_clipboard_disallowed.html
@@ -19,41 +19,33 @@ function doTest()
}
function checkAllowed(event)
{
let clipboardData = event.clipboardData;
let exception;
try {
- clipboardData.mozSetDataAt("text/customdata", document.getElementById("input"), 0);
- } catch(ex) {
- exception = ex;
- }
- is(String(exception).indexOf("SecurityError"), 0, "Cannot set non-string");
-
- exception = null;
- try {
- clipboardData.mozSetDataAt("application/x-moz-file", "Test", 0);
+ clipboardData.setData("application/x-moz-file", "Test");
} catch(ex) {
exception = ex;
}
is(String(exception).indexOf("SecurityError"), 0, "Cannot set file");
exception = null;
try {
- clipboardData.mozSetDataAt("application/x-moz-file-promise", "Test", 0);
+ clipboardData.setData("application/x-moz-file-promise", "Test");
} catch(ex) {
exception = ex;
}
is(String(exception).indexOf("SecurityError"), 0, "Cannot set file promise");
exception = null;
try {
- clipboardData.mozSetDataAt("application/something", "This is data", 0);
+ clipboardData.setData("application/something", "This is data");
} catch(ex) {
exception = ex;
}
is(exception, null, "Can set custom data to a string");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
--- a/dom/tests/mochitest/general/test_clipboard_events.html
+++ b/dom/tests/mochitest/general/test_clipboard_events.html
@@ -297,17 +297,17 @@ add_task(async function test_input_cut_d
// Cut using event.dataTransfer. The event is not cancelled so the default
// cut should occur
selectContentInput();
contentInput.oncut = function(event) {
ok(event instanceof ClipboardEvent, "cut event is a ClipboardEvent");
ok(event.clipboardData instanceof DataTransfer, "cut event dataTransfer is a DataTransfer");
is(event.target, contentInput, "cut event target");
- is(event.clipboardData.mozItemCount, 0, "cut event mozItemCount");
+ is(SpecialPowers.wrap(event.clipboardData).mozItemCount, 0, "cut event mozItemCount");
is(event.clipboardData.getData("text/plain"), "", "cut event getData");
event.clipboardData.setData("text/plain", "This is some dataTransfer text");
cachedCutData = event.clipboardData;
};
try {
await putOnClipboard("INPUT TEXT", () => {
synthesizeKey("x", {accelKey: 1});
}, "cut using dataTransfer on plaintext editor set clipboard correctly");
@@ -344,17 +344,17 @@ add_task(async function test_input_copy_
await reset();
// Copy using event.dataTransfer
selectContentInput();
contentInput.oncopy = function(event) {
ok(event instanceof ClipboardEvent, "copy event is a ClipboardEvent");
ok(event.clipboardData instanceof DataTransfer, "copy event dataTransfer is a DataTransfer");
is(event.target, contentInput, "copy event target");
- is(event.clipboardData.mozItemCount, 0, "copy event mozItemCount");
+ is(SpecialPowers.wrap(event.clipboardData).mozItemCount, 0, "copy event mozItemCount");
is(event.clipboardData.getData("text/plain"), "", "copy event getData");
event.clipboardData.setData("text/plain", "Copied dataTransfer text");
cachedCopyData = event.clipboardData;
};
try {
await putOnClipboard("INPUT TEXT", () => {
synthesizeKey("c", {accelKey: 1});
}, "copy using dataTransfer on plaintext editor set clipboard correctly");
@@ -389,17 +389,17 @@ add_task(async function test_input_paste
await reset();
// Paste using event.dataTransfer
selectContentInput();
contentInput.onpaste = function(event) {
ok(event instanceof ClipboardEvent, "paste event is an ClipboardEvent");
ok(event.clipboardData instanceof DataTransfer, "paste event dataTransfer is a DataTransfer");
is(event.target, contentInput, "paste event target");
- is(event.clipboardData.mozItemCount, 1, "paste event mozItemCount");
+ is(SpecialPowers.wrap(event.clipboardData).mozItemCount, 1, "paste event mozItemCount");
is(event.clipboardData.getData("text/plain"), clipboardInitialValue, "paste event getData");
cachedPasteData = event.clipboardData;
};
try {
synthesizeKey("v", {accelKey: 1});
is(getClipboardText(), clipboardInitialValue,
"paste using dataTransfer on plaintext editor did not modify clipboard contents");
is(contentInput.value, clipboardInitialValue,
@@ -435,31 +435,31 @@ add_task(async function test_input_copyp
// Cut several types of data and paste it again
contentInput.value = "This is a line of text";
contentInput.oncopy = function(event) {
var cd = event.clipboardData;
cd.setData("text/plain", "would be a phrase");
var exh = false;
- try { cd.mozSetDataAt("text/plain", "Text", 1); } catch (ex) { exh = true; }
+ try { SpecialPowers.wrap(cd).mozSetDataAt("text/plain", "Text", 1); } catch (ex) { exh = true; }
ok(exh, "exception occured mozSetDataAt 1");
exh = false;
- try { cd.mozTypesAt(1); } catch (ex) { exh = true; }
+ try { SpecialPowers.wrap(cd).mozTypesAt(1); } catch (ex) { exh = true; }
ok(exh, "exception occured mozTypesAt 1");
exh = false;
- try { cd.mozGetDataAt("text/plain", 1); } catch (ex) { exh = true; }
+ try { SpecialPowers.wrap(cd).mozGetDataAt("text/plain", 1); } catch (ex) { exh = true; }
ok(exh, "exception occured mozGetDataAt 1");
exh = false;
try { cd.mozClearDataAt("text/plain", 1); } catch (ex) { exh = true; }
ok(exh, "exception occured mozClearDataAt 1");
cd.setData("text/x-moz-url", "http://www.mozilla.org");
- cd.mozSetDataAt("text/x-custom", "Custom Text with \u0000 null", 0);
- is(cd.mozItemCount, 1, "mozItemCount after set multiple types");
+ SpecialPowers.wrap(cd).mozSetDataAt("text/x-custom", "Custom Text with \u0000 null", 0);
+ is(SpecialPowers.wrap(cd).mozItemCount, 1, "mozItemCount after set multiple types");
return false;
};
try {
selectContentInput();
await putOnClipboard("would be a phrase", () => {
synthesizeKey("c", {accelKey: 1});
@@ -468,17 +468,17 @@ add_task(async function test_input_copyp
finally {
contentInput.oncopy = null;
}
contentInput.setSelectionRange(5, 14);
contentInput.onpaste = function(event) {
var cd = event.clipboardData;
- is(cd.mozItemCount, 1, "paste after copy multiple types mozItemCount");
+ is(SpecialPowers.wrap(cd).mozItemCount, 1, "paste after copy multiple types mozItemCount");
is(cd.getData("text/plain"), "would be a phrase", "paste text/plain multiple types");
// Firefox for Android's clipboard code doesn't handle x-moz-url. Therefore
// disabling the following test. Enable this once bug #840101 is fixed.
if (!navigator.appVersion.includes("Android")) {
is(cd.getData("text/x-moz-url"), "http://www.mozilla.org", "paste text/x-moz-url multiple types");
is(cd.getData("text/x-custom"), "Custom Text with \u0000 null", "paste text/custom multiple types");
} else {
@@ -635,20 +635,20 @@ function compareSynthetic(event, eventty
if (step == "during") {
is(eventtype, expectedData.type, "synthetic " + eventtype + " event fired");
}
ok(event.clipboardData instanceof DataTransfer, "clipboardData is assigned");
is(event.type, expectedData.type, "synthetic " + eventtype + " event type");
if (expectedData.data === null) {
- is(event.clipboardData.mozItemCount, 0, "synthetic " + eventtype + " empty data");
+ is(SpecialPowers.wrap(event.clipboardData).mozItemCount, 0, "synthetic " + eventtype + " empty data");
}
else {
- is(event.clipboardData.mozItemCount, 1, "synthetic " + eventtype + " item count");
+ is(SpecialPowers.wrap(event.clipboardData).mozItemCount, 1, "synthetic " + eventtype + " item count");
is(event.clipboardData.types.length, 1, "synthetic " + eventtype + " types length");
is(event.clipboardData.getData(expectedData.dataType), expectedData.data,
"synthetic " + eventtype + " data");
}
is(getClipboardText(), "empty", "event does not change the clipboard " + step + " dispatch");
if (step == "during") {
@@ -661,17 +661,17 @@ async function checkCachedDataTransfer(c
await putOnClipboard("Some Clipboard Text", () => { setClipboardText("Some Clipboard Text") },
"change clipboard outside of event");
var oldtext = cd.getData("text/plain");
ok(!oldtext, "clipboard get using " + testprefix);
try {
- cd.mozSetDataAt("text/plain", "Test Cache Data", 0);
+ SpecialPowers.wrap(cd).mozSetDataAt("text/plain", "Test Cache Data", 0);
} catch (ex) {}
ok(!cd.getData("text/plain"), "clipboard set using " + testprefix);
is(getClipboardText(), "Some Clipboard Text", "clipboard not changed using " + testprefix);
try {
cd.mozClearDataAt("text/plain", 0);
} catch (ex) {}
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/test_datatransfer_disallowed.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for DataTransfer moz* APIs</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script>
+function run_test()
+{
+ SpecialPowers.pushPrefEnv({"set": [
+ ["dom.datatransfer.moz", false],
+ ]}, function() {
+ let hiddenMethods = ["mozTypesAt", "mozClearDataAt", "mozGetDataAt", "mozSetDataAt", "mozItemCount"];
+ let exposedMethods = Object.getOwnPropertyNames(DataTransfer.prototype);
+ for (var idx in hiddenMethods) {
+ if (exposedMethods.includes(hiddenMethods[idx])) {
+ ok(false, hiddenMethods[idx] + " should not be exposed");
+ } else {
+ ok(true, hiddenMethods[idx] + " was not exposed");
+ }
+ }
+ SimpleTest.finish();
+ });
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(run_test);
+</script>
--- a/dom/webidl/DataTransfer.webidl
+++ b/dom/webidl/DataTransfer.webidl
@@ -49,17 +49,17 @@ partial interface DataTransfer {
* @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
*/
[Throws, UseCounter]
void addElement(Element element);
/**
* The number of items being dragged.
*/
- [UseCounter]
+ [Func="DataTransfer::MozAtAPIsEnabled"]
readonly attribute unsigned long mozItemCount;
/**
* Sets the drag cursor state. Primarily used to control the cursor during
* tab drags, but could be expanded to other uses. XXX Currently implemented
* on Win32 only.
*
* Possible values:
@@ -72,34 +72,34 @@ partial interface DataTransfer {
[UseCounter]
attribute DOMString mozCursor;
/**
* Holds a list of the format types of the data that is stored for an item
* at the specified index. If the index is not in the range from 0 to
* itemCount - 1, an empty string list is returned.
*/
- [Throws, NeedsCallerType, UseCounter]
+ [Throws, NeedsCallerType, Func="DataTransfer::MozAtAPIsEnabled"]
DOMStringList mozTypesAt(unsigned long index);
/**
* Remove the data associated with the given format for an item at the
* specified index. The index is in the range from zero to itemCount - 1.
*
* If the last format for the item is removed, the entire item is removed,
* reducing the itemCount by one.
*
* If format is empty, then the data associated with all formats is removed.
* If the format is not found, then this method has no effect.
*
* @param format the format to remove
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater or equal than itemCount
* @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
*/
- [Throws, NeedsSubjectPrincipal, UseCounter]
+ [Throws, NeedsSubjectPrincipal, Func="DataTransfer::MozAtAPIsEnabled"]
void mozClearDataAt(DOMString format, unsigned long index);
/*
* A data transfer may store multiple items, each at a given zero-based
* index. setDataAt may only be called with an index argument less than
* itemCount in which case an existing item is modified, or equal to
* itemCount in which case a new item is added, and the itemCount is
* incremented by one.
@@ -113,29 +113,29 @@ partial interface DataTransfer {
* (which will be converted into a string) or an nsISupports.
*
* @param format the format to add
* @param data the data to add
* @throws NS_ERROR_NULL_POINTER if the data is null
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater than itemCount
* @throws NO_MODIFICATION_ALLOWED_ERR if the item cannot be modified
*/
- [Throws, NeedsSubjectPrincipal, UseCounter]
+ [Throws, NeedsSubjectPrincipal, Func="DataTransfer::MozAtAPIsEnabled"]
void mozSetDataAt(DOMString format, any data, unsigned long index);
/**
* Retrieve the data associated with the given format for an item at the
* specified index, or null if it does not exist. The index should be in the
* range from zero to itemCount - 1.
*
* @param format the format of the data to look up
* @returns the data of the given format, or null if it doesn't exist.
* @throws NS_ERROR_DOM_INDEX_SIZE_ERR if index is greater or equal than itemCount
*/
- [Throws, NeedsSubjectPrincipal, UseCounter]
+ [Throws, NeedsSubjectPrincipal, Func="DataTransfer::MozAtAPIsEnabled"]
any mozGetDataAt(DOMString format, unsigned long index);
/**
* Update the drag image. Arguments are the same as setDragImage. This is only
* valid within the parent chrome process.
*/
[ChromeOnly]
void updateDragImage(Element image, long x, long y);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5854,8 +5854,15 @@ pref("browser.fastblock.enabled", false)
// after this timeout will be canceled.
pref("browser.fastblock.timeout", 5000);
// Disables clipboard reads and writes by default.
pref("dom.events.asyncClipboard", false);
pref("dom.events.asyncClipboard.dataTransfer", false);
// Should only be enabled in tests
pref("dom.events.testing.asyncClipboard", false);
+
+#ifdef NIGHTLY_BUILD
+// Disable moz* APIs in DataTransfer
+pref("dom.datatransfer.mozAtAPIs", false);
+#else
+pref("dom.datatransfer.mozAtAPIs", true);
+#endif
--- a/testing/mochitest/tests/SimpleTest/EventUtils.js
+++ b/testing/mochitest/tests/SimpleTest/EventUtils.js
@@ -2579,17 +2579,17 @@ function synthesizeDragOver(aSrcElement,
// This method runs before other callbacks, and acts as a way to inject the
// initial drag data into the DataTransfer.
function fillDrag(event) {
if (aDragData) {
for (var i = 0; i < aDragData.length; i++) {
var item = aDragData[i];
for (var j = 0; j < item.length; j++) {
- event.dataTransfer.mozSetDataAt(item[j].type, item[j].data, i);
+ SpecialPowers.wrap(event.dataTransfer).mozSetDataAt(item[j].type, item[j].data, i);
}
}
}
event.dataTransfer.dropEffect = aDropEffect || "move";
event.preventDefault();
}
function trapDrag(subject, topic) {