Bug 1453153 - Initial removal of moz* APIs in DataTransfer, r=enndeakin,nika

In DataTransfer, change mozItemCount, mozTypesAt, mozClearDataAt, mozSetDataAt,
mozGetDataAt APIs to be ChromeOnly.

MozReview-Commit-ID: 9uJ9ncrcBL2
This commit is contained in:
Anny Gakhokidze 2018-06-18 23:43:31 -04:00 коммит произвёл Nika Layzell
Родитель b6a3ba71f1
Коммит be49493caf
13 изменённых файлов: 104 добавлений и 48 удалений

Просмотреть файл

@ -42,6 +42,7 @@ var dragLinkText = [[
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);

Просмотреть файл

@ -40,6 +40,8 @@
#include "mozilla/dom/Promise.h"
#include "nsNetUtil.h"
#define MOZ_CALLS_ENABLED_PREF "dom.datatransfer.mozAtAPIs"
namespace mozilla {
namespace dom {
@ -1523,5 +1525,22 @@ DataTransfer::SetMode(DataTransfer::Mode 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

Просмотреть файл

@ -428,6 +428,11 @@ public:
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

Просмотреть файл

@ -1,6 +1,6 @@
<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>
@ -10,7 +10,7 @@
<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>

Просмотреть файл

@ -30,7 +30,7 @@ function runTests()
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");
}

Просмотреть файл

@ -41,10 +41,6 @@ function afterDragTests()
"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");
@ -130,7 +126,7 @@ function doDragStartSelection(event)
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");
@ -143,10 +139,14 @@ function doDragStartSelection(event)
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");
@ -316,11 +316,9 @@ function test_DataTransfer(dt)
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") {
@ -329,7 +327,7 @@ function test_DataTransfer(dt)
}
}
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);
@ -419,7 +417,7 @@ function doDragStartLink(event)
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");
@ -436,7 +434,7 @@ function doDragStartImage(event)
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");
@ -450,7 +448,7 @@ 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();
@ -511,11 +509,12 @@ function doDragOverSynthetic(event)
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);
@ -537,13 +536,14 @@ function checkTypes(dt, expectedtypes, index, testid)
}
}
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");

Просмотреть файл

@ -90,6 +90,7 @@ 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]

Просмотреть файл

@ -24,15 +24,7 @@ function checkAllowed(event)
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;
}
@ -40,7 +32,7 @@ function checkAllowed(event)
exception = null;
try {
clipboardData.mozSetDataAt("application/x-moz-file-promise", "Test", 0);
clipboardData.setData("application/x-moz-file-promise", "Test");
} catch(ex) {
exception = ex;
}
@ -48,7 +40,7 @@ function checkAllowed(event)
exception = null;
try {
clipboardData.mozSetDataAt("application/something", "This is data", 0);
clipboardData.setData("application/something", "This is data");
} catch(ex) {
exception = ex;
}

Просмотреть файл

@ -302,7 +302,7 @@ add_task(async function test_input_cut_dataTransfer() {
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;
@ -349,7 +349,7 @@ add_task(async function test_input_copy_dataTransfer() {
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;
@ -394,7 +394,7 @@ add_task(async function test_input_paste_dataTransfer() {
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;
};
@ -440,21 +440,21 @@ add_task(async function test_input_copypaste_dataTransfer_multiple() {
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;
};
@ -473,7 +473,7 @@ add_task(async function test_input_copypaste_dataTransfer_multiple() {
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
@ -640,10 +640,10 @@ function compareSynthetic(event, eventtype) {
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");
@ -666,7 +666,7 @@ async function checkCachedDataTransfer(cd, eventtype) {
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);

Просмотреть файл

@ -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>

Просмотреть файл

@ -54,7 +54,7 @@ partial interface DataTransfer {
/**
* The number of items being dragged.
*/
[UseCounter]
[Func="DataTransfer::MozAtAPIsEnabled"]
readonly attribute unsigned long mozItemCount;
/**
@ -77,7 +77,7 @@ partial interface DataTransfer {
* 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);
/**
@ -94,7 +94,7 @@ partial interface DataTransfer {
* @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);
/*
@ -118,7 +118,7 @@ partial interface DataTransfer {
* @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);
/**
@ -130,7 +130,7 @@ partial interface DataTransfer {
* @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);
/**

Просмотреть файл

@ -5900,3 +5900,10 @@ 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

Просмотреть файл

@ -2584,7 +2584,7 @@ function synthesizeDragOver(aSrcElement, aDestElement, aDragData, aDropEffect, a
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);
}
}
}