クリップボードAPIは、Permissions.request()が実装されるまで使用するのを先延ばしにした

# はじめに

社内向けのWeb開発を行なっている際、クライアント(ブラウザ)側でテキストを保持させておく要件が発生しました。

これを実現させるため、クリップボードAPIに目をつけ、調査・判断したことを書き残しておきます。

クリップボードAPIの使用を検討されていた方の参考になれば幸いです。 :pray: 

## 書くこと

- クリップボードAPIの概要
- クリップボードAPIを使うのを先延ばしにした理由と、代替手段

# クリップボードAPIとは？

名前の通り、
ブラウザからクリップボード（コピー、切り取り、貼り付け）の操作を行うAPIです。

- [MDN - クリップボード API](https://developer.mozilla.org/ja/docs/Web/API/Clipboard_API)

クリップボードAPIの説明文にも記載されている通り、
以前は[Document.execCommand](https://developer.mozilla.org/ja/docs/Web/API/Document/execCommand)を用いて
クリップボード相当の動作を実現できました。

しかし、`Document.execCommand`が廃止され、
代わりに用意されたのがクリップボードAPIとのことです。

## デモ

簡単ですが、クリップボードAPIのデモを用意しました。
実際の挙動を確認されたい方は、
お手数ですが、以下のデモ・ソースをご参照ください。

- ソース: [javascript-sandbox/clipboard-sample](https://github.com/zakizaki-ri9/javascript-sandbox/tree/release/clipboard-sample/clipboard-sample)
    - [src/components/Clipboard.vue](https://github.com/zakizaki-ri9/javascript-sandbox/blob/release/clipboard-sample/clipboard-sample/src/components/Clipboard.vue)
- デプロイ先: https://clipboard-sample.vercel.app/

## 使用はブラウザ側の許可が必要

MDNのドキュメントに記載されている通り、クリップボードAPIは、
ブラウザ側でクリップボードの使用許可が必要となります。

クリップボードAPIの許可・未許可・拒否の状態は、
PermissionsAPIで提供されている[query()](https://developer.mozilla.org/ja/docs/Web/API/Permissions/query)で確認できます。



# クリップボードAPIを使うのを先延ばしにした

理由は2つあります。

## 理由1「ユーザー側で、意図せずクリップボードの拒否をしてしまった場合、対処が大変」

クリップボードAPIは、読み書きでPermissionsが異なります。

- クリップボードの読み込み - `clipboard-read`
- クリップボードの書き込み - `clipboard-write`

`clipboard-write`は、初期状態で許可されているため、
ブラウザの設定から意図して拒否しない限りは、問題なく使えるかと思います。

しかし、
`clipboard-read`は、初期状態では未許可状態。
以下、クリップボードの読み込み系のAPIを実行した際に、

- [navigator.clipboard.read()](https://developer.mozilla.org/ja/docs/Web/API/Clipboard/read)
- [navigator.clipboard.readText()](https://developer.mozilla.org/ja/docs/Web/API/Clipboard/readText)

許可・拒否を選択する、
以下のようなプロンプトが表示されます。

![スクリーンショット 2020-07-18 8.42.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140704/4c99474a-d60c-8e4c-2907-897db12b0942.png)

意図せずブロックを選択してしまった場合、**ChromeやFirefoxといったブラウザごと、設定画面からブロック解除する操作を行なっていただく必要があります。**

このような場合、

- ユーザー側で、ブロック解除する方法を求む問い合わせするコストがかかる
- 問い合わせを受けた、開発側（プログラマーや情シス）の返信コストがかかる

と、ユーザー・開発の双方にコストがかかると想定できます。[^1]

[^1]: ブロック解除するFAQページを作っておく方法もありますが、FAQページに誘導する導線整備まで行うコストをかけられないと判断しました。

よって、クリップボードAPIの使用を諦めました。

## 理由2「`Permissions.request()`の実装を待つ」

[MDN - Permissions API の使用](https://developer.mozilla.org/ja/docs/Web/API/Permissions_API/Using_the_Permissions_API)の画面下部「まとめと今後の課題」には、理由1と同等の課題感が記載されていました。

また、ユーザー側に権限許可を要求する`Permissions.request()`という関数をいずれ提供する...ような記載がありました。

`Permissions.request()`が実装されれば、以下のような実装（クリップボードの許可確認を再度要求すること）が可能となり、問い合わせは不要となります。

```js
async function onPasteClicked() {
  // クリップボードの読み取りを要求
  const isClipboardRead = await navigator.permissions.request({ name: 'clipboard-read' })
  if (isClipboardRead) {
    // 許可された場合の処理
  } else {
    // 拒否された場合の処理
  }
}
```

よって、`Permissions.request()`が実装されるまで、クリップボードAPIの使用は先延ばしとする判断をとりました。

# 代替手段

テキストをブラウザ側に保存させておく方法はいくつかあります。

- [localStorage](https://developer.mozilla.org/ja/docs/Web/API/Window/localStorage)
- [sessionStorage](https://developer.mozilla.org/ja/docs/Web/API/Window/sessionStorage)
- [IndexedDB API](https://developer.mozilla.org/ja/docs/Web/API/IndexedDB_API)
- [Cache](https://developer.mozilla.org/ja/docs/Web/API/Cache)

今回は、複数タブにまたがって情報を保持するという理由から、`localStorage`する方向で判断しました。

しかし、以下の記事にも記載されている通り、`localStorage`と`sessionStorage`は容易に参照できてしまうため、今後別のものに置き換えていきたいです。

- [HTML5のLocal Storageを使ってはいけない（翻訳）](https://techracho.bpsinc.jp/hachi8833/2019_10_09/80851)

# おわり

以上になります。

間違い等ありましたら、やさしめにFBいただけると幸いです。 :pray: