Bug 1398883 - Disable the DataTransfer::Protected state for Firefox 57, r=baku

This isn't a super essential feature, and is just a change to try to bring us in
line with chromium and the spec. As this has apparent web compat issues, and
DataTransfer is a hard to test area, this patch moves the changes behind a pref,
which we can come back to turning on after we ship 57.
This commit is contained in:
Michael Layzell 2017-09-11 15:35:16 -04:00
Родитель c24551af0d
Коммит 5dff36164d
7 изменённых файлов: 66 добавлений и 12 удалений

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

@ -845,8 +845,16 @@ nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
// all stored data, before we return.
auto clearAfter = MakeScopeExit([&] {
if (clipboardData) {
clipboardData->SetMode(DataTransfer::Mode::Protected);
clipboardData->ClearAll();
clipboardData->Disconnect();
// NOTE: Disconnect may not actually clear the DataTransfer if the
// dom.events.dataTransfer.protected.enabled pref is not on, so we make
// sure we clear here, as not clearing could provide the DataTransfer
// access to information from the system clipboard at an arbitrary point
// in the future.
if (originalEventMessage == ePaste) {
clipboardData->ClearAll();
}
}
});

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

@ -81,6 +81,23 @@ enum CustomClipboardTypeId {
eCustomClipboardTypeId_String
};
// The dom.events.dataTransfer.protected.enabled preference controls whether or
// not the `protected` dataTransfer state is enabled. If the `protected`
// dataTransfer stae is disabled, then the DataTransfer will be read-only
// whenever it should be protected, and will not be disconnected after a drag
// event is completed.
static bool
PrefProtected()
{
static bool sInitialized = false;
static bool sValue = false;
if (!sInitialized) {
sInitialized = true;
Preferences::AddBoolVarCache(&sValue, "dom.events.dataTransfer.protected.enabled");
}
return sValue;
}
static DataTransfer::Mode
ModeForEvent(EventMessage aEventMessage)
{
@ -98,7 +115,9 @@ ModeForEvent(EventMessage aEventMessage)
// the DataTransfer, rather than just the type information.
return DataTransfer::Mode::ReadOnly;
default:
return DataTransfer::Mode::Protected;
return PrefProtected()
? DataTransfer::Mode::Protected
: DataTransfer::Mode::ReadOnly;
}
}
@ -1276,6 +1295,15 @@ DataTransfer::ConvertFromVariant(nsIVariant* aVariant,
return true;
}
void
DataTransfer::Disconnect()
{
SetMode(Mode::Protected);
if (PrefProtected()) {
ClearAll();
}
}
void
DataTransfer::ClearAll()
{
@ -1608,5 +1636,15 @@ DataTransfer::FillInExternalCustomTypes(nsIVariant* aData, uint32_t aIndex,
} while (type != eCustomClipboardTypeId_None);
}
void
DataTransfer::SetMode(DataTransfer::Mode aMode)
{
if (!PrefProtected() && aMode == Mode::Protected) {
mMode = Mode::ReadOnly;
} else {
mMode = aMode;
}
}
} // namespace dom
} // namespace mozilla

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

@ -229,9 +229,7 @@ public:
Mode GetMode() const {
return mMode;
}
void SetMode(Mode aMode) {
mMode = aMode;
}
void SetMode(Mode aMode);
// Helper method. Is true if the DataTransfer's mode is ReadOnly or Protected,
// which means that the DataTransfer cannot be modified.
@ -272,6 +270,12 @@ public:
nsISupports** aSupports,
uint32_t* aLength) const;
// Disconnects the DataTransfer from the Drag Data Store. If the
// dom.dataTransfer.disconnect pref is enabled, this will clear the
// DataTransfer and set it to the `Protected` state, otherwise this method is
// a no-op.
void Disconnect();
// clears all of the data
void ClearAll();

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

@ -1774,8 +1774,7 @@ EventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
new DataTransfer(window, eDragStart, false, -1);
auto protectDataTransfer = MakeScopeExit([&] {
if (dataTransfer) {
dataTransfer->SetMode(DataTransfer::Mode::Protected);
dataTransfer->ClearAll();
dataTransfer->Disconnect();
}
});

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

@ -74,7 +74,7 @@ function runTests()
SpecialPowers.addChromeEventListener("drop", chromeListener, true, false);
var targetNotHandling = document.getElementById("nothandling_target");
fireDrop(targetNotHandling, false, true);
fireDrop(targetNotHandling, true, true);
SpecialPowers.removeChromeEventListener("drop", chromeListener, true);
ok(chromeGotEvent, "Chrome should have got drop event!");
is(gGotHandlingDrop, false, "Didn't get drop on accepting element (2)");

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

@ -746,7 +746,13 @@ function test_image_dataTransfer() {
}
}
SimpleTest.waitForFocus(doTests);
SimpleTest.waitForFocus(() => {
SpecialPowers.pushPrefEnv({
// NOTE: These tests operate under the assumption that the protected mode of
// DataTransfer is enabled.
"set": [["dom.events.dataTransfer.protected.enabled", true]]
}, doTests);
});
</script>
</pre>

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

@ -8246,8 +8246,7 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent,
// made protected, and then disconnected.
DataTransfer* dataTransfer = aEvent->AsDragEvent()->mDataTransfer;
if (dataTransfer) {
dataTransfer->SetMode(DataTransfer::Mode::Protected);
dataTransfer->ClearAll();
dataTransfer->Disconnect();
}
break;
}