chromium/third_party/blink/web_tests/fast/dnd/resources/copy-data-transfer.js

'use strict';

// Copies the information out of a DataTransfer instance. This is necessary
// because dataTransfer instances get neutered after their event handlers exit.
//
// Returns a Promise that resolves to an object which mirrors the DataTransfer's
// files, items, and types attributes, as well as the return values of the
// getData function. The contents of files and file items are read using
// FileReader.
const copyDataTransfer = dataTransfer => {
  const types = dataTransfer.types.slice();
  const data = {};
  for (let type of types) {
    try {
      data[type] = dataTransfer.getData(type);
    } catch(e) {  // Catches SecurityError exceptions.
      data[type] = e;
    }
  }

  const readerPromises = [];

  const files = [];
  for (let file of Array.from(dataTransfer.files || [])) {
    const fileData = { file: file };
    files.push(fileData);

    readerPromises.push(new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onloadend = event => {
        if (event.target.error)
          fileData.error = event.target.error;
        else
          fileData.data = event.target.result;
        resolve();
      };
      reader.readAsText(file);
    }).catch(e => fileData.error = e));
  }

  const items = [];
  for (let item of Array.from(dataTransfer.items || [])) {
    const itemData = { kind: item.kind, type: item.type };
    items.push(itemData);

    readerPromises.push(new Promise((resolve, reject) => {
      if (itemData.kind === 'file') {
        itemData.file = item.getAsFile();
        if (itemData.file === null) {  // DataTransfer is in protected mode.
          resolve();
          return;
        }

        const reader = new FileReader();
        reader.onloadend = event => {
          if (event.target.error)
            itemData.data = event.target.error;
          else
            itemData.data = event.target.result;
          resolve();
        };
        reader.readAsText(itemData.file);
      }
    }).catch(e => itemData.error = e));
  }

  return Promise.all(readerPromises).then(() => {
    return { data, files, items, types };
  });
};