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. // all stored data, before we return.
auto clearAfter = MakeScopeExit([&] { auto clearAfter = MakeScopeExit([&] {
if (clipboardData) { if (clipboardData) {
clipboardData->SetMode(DataTransfer::Mode::Protected); clipboardData->Disconnect();
clipboardData->ClearAll();
// 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 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 static DataTransfer::Mode
ModeForEvent(EventMessage aEventMessage) ModeForEvent(EventMessage aEventMessage)
{ {
@ -98,7 +115,9 @@ ModeForEvent(EventMessage aEventMessage)
// the DataTransfer, rather than just the type information. // the DataTransfer, rather than just the type information.
return DataTransfer::Mode::ReadOnly; return DataTransfer::Mode::ReadOnly;
default: default:
return DataTransfer::Mode::Protected; return PrefProtected()
? DataTransfer::Mode::Protected
: DataTransfer::Mode::ReadOnly;
} }
} }
@ -1276,6 +1295,15 @@ DataTransfer::ConvertFromVariant(nsIVariant* aVariant,
return true; return true;
} }
void
DataTransfer::Disconnect()
{
SetMode(Mode::Protected);
if (PrefProtected()) {
ClearAll();
}
}
void void
DataTransfer::ClearAll() DataTransfer::ClearAll()
{ {
@ -1608,5 +1636,15 @@ DataTransfer::FillInExternalCustomTypes(nsIVariant* aData, uint32_t aIndex,
} while (type != eCustomClipboardTypeId_None); } while (type != eCustomClipboardTypeId_None);
} }
void
DataTransfer::SetMode(DataTransfer::Mode aMode)
{
if (!PrefProtected() && aMode == Mode::Protected) {
mMode = Mode::ReadOnly;
} else {
mMode = aMode;
}
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

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

@ -229,9 +229,7 @@ public:
Mode GetMode() const { Mode GetMode() const {
return mMode; return mMode;
} }
void SetMode(Mode aMode) { void SetMode(Mode aMode);
mMode = aMode;
}
// Helper method. Is true if the DataTransfer's mode is ReadOnly or Protected, // Helper method. Is true if the DataTransfer's mode is ReadOnly or Protected,
// which means that the DataTransfer cannot be modified. // which means that the DataTransfer cannot be modified.
@ -272,6 +270,12 @@ public:
nsISupports** aSupports, nsISupports** aSupports,
uint32_t* aLength) const; 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 // clears all of the data
void ClearAll(); void ClearAll();

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

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

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

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

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

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