Files
sousa-gecko/testing/web-platform/tests/html/editing/dnd/js-file-fallback-text-only.html
T
Joone Hur da3eaa53bf Bug 2038082 [wpt PR 59744] - Support dragging JS File objects to native drop targets, a=testonly
Automatic update from web-platform-tests
Support dragging JS File objects to native drop targets

When a web app places a JS File object (new File([bytes], 'photo.jpg'))
into a dragstart handler, the blob bytes were previously discarded in
DataObject::ToWebDragData().

This CL reads the blob bytes synchronously at drag-start time using
SyncedFileReaderAccumulator::Load() and passes them as a BinaryDataItem
through the IPC pipeline. Platform-specific delivery to native drop
targets is handled by the existing PrepareDragForFileContents() path,
which is already enabled for Linux, ChromeOS, and Windows via BUILDFLAG
guards in web_contents_view_aura.cc.

Currently, image file types are supported via the
GetSafeFilenameForImageFileContents() gate.

To enable this feature, launch Chrome with:
--enable-blink-features=DragAndDropJSFileObjects

Bug: 41120809
Change-Id: Ibe12d867f7d01a972b7aeb6ce55660adb7300b27
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7603160
Reviewed-by: Rohan Raja <roraja@microsoft.com>
Reviewed-by: Kent Tamura <tkent@chromium.org>
Commit-Queue: Joone Hur <joonehur@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1627402}

--

wpt-commits: 6fd907a40e68c632146df346deba6ba60299e2d5
wpt-pr: 59744
2026-05-12 08:48:30 +00:00

100 lines
3.1 KiB
HTML

<!doctype html>
<meta charset="utf-8">
<title>Drag and Drop: JS File Object (fallback to text/plain when feature disabled)</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com">
<link rel="help" href="https://html.spec.whatwg.org/multipage/dnd.html#the-datatransfer-interface">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<style>
.box {
display: inline-block;
border: 2px solid black;
width: 100px;
height: 100px;
margin: 20px;
vertical-align: top;
line-height: 100px;
text-align: center;
}
#drag-src { background: lightblue; }
#drop-tgt { background: lightgrey; }
</style>
<div id="drag-src" class="box" draggable="true">Source</div>
<div id="drop-tgt" class="box">Target</div>
<script>
'use strict';
function makePngBytes() {
const canvas = document.createElement('canvas');
canvas.width = 1; canvas.height = 1;
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 1, 1);
const bin = atob(canvas.toDataURL('image/png').split(',')[1]);
return Uint8Array.from(bin, c => c.charCodeAt(0));
}
const PNG_BYTES = makePngBytes();
// This test verifies the fallback path when DragAndDropJSFileObjects is
// disabled: a JS-constructed File object should be transferred as text/plain
// containing only the filename, with no binary file content available.
promise_test(async t => {
const dragSrc = document.getElementById('drag-src');
const dropTgt = document.getElementById('drop-tgt');
const dropWatcher = new Promise((resolve, reject) => {
dragSrc.ondragstart = t.step_func(e => {
const file = new File([PNG_BYTES], 'test.png', {type: 'image/png'});
e.dataTransfer.items.add(file);
e.dataTransfer.effectAllowed = 'copy';
});
dropTgt.ondragenter = e => {
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
};
dropTgt.ondragover = e => {
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
};
dropTgt.ondrop = t.step_func(async e => {
e.preventDefault();
try {
// When the feature is disabled, no binary file content is transferred.
assert_equals(e.dataTransfer.files.length, 0,
'No files should be in .files when feature is disabled');
// The filename should be available as text/plain.
const text = e.dataTransfer.getData('text/plain');
assert_equals(text, 'test.png',
'Filename should be transferred as text/plain fallback');
resolve();
} catch (err) {
reject(err);
}
});
});
await new test_driver.Actions()
.pointerMove(0, 0, {origin: dragSrc})
.pointerDown()
.pause(100)
.pointerMove(15, 15, {origin: dragSrc})
.pause(100)
.pointerMove(0, 0, {origin: dropTgt})
.pause(100)
.pointerUp()
.send();
await dropWatcher;
}, 'JS File falls back to text/plain filename when DragAndDropJSFileObjects is disabled');
</script>