Async Clipboard API のウェブ カスタム フォーマット

これまで、Async Clipboard API では、システム クリップボードとの間でコピー、貼り付けできる MIME タイプ(具体的には text/plaintext/htmlimage/png)が限定されていました。通常、ブラウザはこれをサニタイズして、埋め込まれた script 要素や javascript: リンクを HTML 文字列から削除する、または PNG 解凍爆弾攻撃を防止するなどの処理を行います。

ただし、クリップボード上のサニタイズされていないコンテンツをサポートすることが望ましい場合もあります。

  • アプリケーションがサニタイズ自体を処理する状況。
  • コピーしたデータと貼り付けたデータが同じであることが重要な状況。

このような場合、Async Clipboard API はウェブ カスタム形式に対応し、デベロッパーが任意のデータをクリップボードに書き込むことができます。

ブラウザ サポート

Chromium 76 以降では、画像をサポートする Async Clipboard API 自体がサポートされています。Async Clipboard API のウェブ カスタム形式は、パソコンとモバイルの Chromium バージョン 104 以降でサポートされています。

ウェブ カスタム形式をクリップボードに書き込む

ウェブ カスタム形式をクリップボードに書き込む方法は、サニタイズされた形式を書き込む場合とほぼ同じですが、blob の MIME タイプの先頭に文字列 "web "(末尾のスペースを含む)を追加する点が異なります。

// Fetch remote JPEG and GIF images and obtain their blob representations.
const [jpegBlob, gifBlob] = await Promise.all([
  fetch('image.jpg').then((response) => response.blob()),
  fetch('image.gif').then((response) => response.blob()),
]);

try {
  // Write the image data to the clipboard, prepending the blobs' actual
  // types (`"image/jpeg"` and "image/gif") with the string `"web "`, so
  // they become `"web image/jpeg"` and `"web image/gif"` respectively.
  // The code elegantly makes use of computed property names:
  // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Object_initializer#computed_property_names.
  const clipboardItem = new ClipboardItem({
    [`web ${jpegBlob.type}`]: jpegBlob,
    [`web ${gifBlob.type}`]: gifBlob,
  });
  await navigator.clipboard.write([clipboardItem]);
} catch (err) {
  console.error(err.name, err.message);
}

クリップボードからウェブ カスタム形式を読み取る

書き込みと同様に、クリップボードからウェブ カスタム形式を読み取ることは、サニタイズされた形式を読み取るのとほぼ同じです。唯一の違いは、タイプが "web " で始まるクリップボード アイテムをアプリが検索する必要がある点です。

try {
  // Iterate over all clipboard items.
  const clipboardItems = await navigator.clipboard.read();
  for (const clipboardItem of clipboardItems) {
    for (const type of clipboardItem.types) {
      // Discard any types that are not web custom formats.
      if (!type.startsWith('web ')) {
        continue;
      }
      const blob = await clipboardItem.getType(type);
      // Sanitize the blob if you need to, then process it in your app.
    }
  }
} catch (err) {
  console.error(err.name, err.message);
}

プラットフォーム固有のアプリとの相互運用性

web image/jpeg などのウェブ カスタム フォーマットは、一般的なプラットフォーム固有のアプリが認識できるものではありません(image/jpeg を想定しているため)。今後、関係するアプリは、デベロッパーがユーザーに関連するウェブ カスタム フォーマットのサポートと判断した場合、オプトインなどのフォーマットのサポートを追加することが予想されます。以下の macOS のスクリーンショットに示すように、オペレーティング システムのクリップボードにはさまざまな形式が複数の形式で用意されており、すぐに使用できます。

2 つのウェブ カスタム フォーマットをリストしたカスタム フォーマット マップを表示している macOS のクリップボード Expector。

デモ

以下のデモを試し、ソースコードを表示してデモの動作を確認できます。

謝辞

この記事は、Joe MedleyFrançois Beaufort によってレビューされました。Neon Tommy 氏によるヒーロー画像。CC BY-SA 2.0 ライセンスに基づき使用。