David Anderson
David Anderson

Reputation: 13680

What is the data format specification for "Chromium Web Custom MIME Data Format"?

I have a WPF application that supports receiving drag and drop data from Chrome. When the data is received by IDataObject the data format is "Chromium Web Custom MIME Data Format". This is because I use custom MIME type for dataTransfer.setData from JavaScript. This is expected behavior.

My question is, what is the actual specification for this data?

The data is a MemoryStream of bytes that I can convert to a Unicode string. Given a MIME type of application/x-myapp.document+text and a value of {F5F5A3C3-3594-430B-988F-BA1C0154201E} the string will look like the following:

" \0\u0001\0#\0application/x-myapp.document+text\0&\0{F5F5A3C3-3594-430B-988F-BA1C0154201E}"

If I split the string by the null terminators it is six parts:

  1. (_determined this to be the size of the data (length) and is not any real character of a string)
  2. \u0001 (determined this to be the number of data items)
  3. #
  4. application/x-myapp.document+text (the custom MIME type)
  5. &
  6. {F5F5A3C3-3594-430B-988F-BA1C0154201E} (the custom value)

I have observed that #2 is just a number and seems to represent the number of key value pairs in the data (mime/value). Then I have my MIME type, and actual value. It appears that this data is the HTML 5 Drag Data Store, or possibly the drag store item list.

So again, my final questions:

I also will need to do this with Firefox and the data appears to be similar, but possibly with a different Encoding. So if this is known information also, it would be helpful.

I have also tried using a BinaryReader but without a specification I have been unable to read the data in a manner that produces correct results, and I have been using the HTML 5 spec (https://html.spec.whatwg.org/multipage/dnd.html#the-drag-data-store).

Upvotes: 2

Views: 1379

Answers (1)

Coragi
Coragi

Reputation: 61

You find the source code of Chromium here: https://chromium.googlesource.com/chromium/chromium/+/refs/heads/main/ui/base/clipboard/clipboard_util_win.cc

To read "Chromium Web Custom MIME Data Format":

bool ClipboardUtil::GetWebCustomData(
    IDataObject* data_object, std::map<string16, string16>* custom_data) {
  DCHECK(data_object && custom_data);
  if (FAILED(data_object->QueryGetData(GetWebCustomDataFormat())))
    return false;
  STGMEDIUM store;
  if (SUCCEEDED(data_object->GetData(GetWebCustomDataFormat(), &store))) {
    {
      base::win::ScopedHGlobal<char> data(store.hGlobal);
      ReadCustomDataIntoMap(data.get(), data.Size(), custom_data);
    }
    ReleaseStgMedium(&store);
    return true;
  }
  return false;
}

Parsing of the actual data is done in the following method:

https://chromium.googlesource.com/chromium/src/+/refs/heads/main/ui/base/clipboard/custom_data_helper.cc

void ReadCustomDataIntoMap(
    const void* data,
    size_t data_length,
    std::unordered_map<std::u16string, std::u16string>* result) {
  base::Pickle pickle(reinterpret_cast<const char*>(data), data_length);
  base::PickleIterator iter(pickle);
  uint32_t size = 0;
  if (!iter.ReadUInt32(&size))
    return;
  for (uint32_t i = 0; i < size; ++i) {
    std::u16string type;
    if (!iter.ReadString16(&type)) {
      // Data is corrupt, return an empty map.
      result->clear();
      return;
    }
    auto insert_result = result->insert({type, std::u16string()});
    if (!iter.ReadString16(&insert_result.first->second)) {
      // Data is corrupt, return an empty map.
      result->clear();
      return;
    }
  }
}

The first UInt32 is the number of Key/Value pairs. Then loop through the items by reading the Key name (String16) and Value (String16).

Upvotes: 1

Related Questions