本記事の目的
8/31 readText()の動作確認を追記しました。
以前navigator.clipboardについてこんな記事を書きました
この時に、やけにChromeのclipboard APIの実装が他のブラウザと比べて緩いなーと思っていたのですが・・・
するとこんなニュース記事が発表されており
GitHubでtomayac氏が投稿した内容によると、画像をクリップボードにコピーするAPIのメソッド「navigator.clipboard.write()」および文字列をクリップボードにコピーするAPIのメソッド「navigator.clipboard.writeText()」は、FirefoxとSafariではユーザーによる操作が求められるのですが、Chromeではユーザーの操作なしで実行されるとのこと。Naleksuh氏は「これは以前から問題になっていたものです。この問題があるので、ランダムなウェブサイトでJavaScriptを有効にすべきではないのです」とコメントしています。
とのこと。以前利用したのはclipboard.readText()だったので気がつかなかったのですが、どうやら今の実装だと
clipboard.writeText()はユーザにパーミッションを取らずに動作してしまうらしい?
とのことなので、動作検証してみました。
検証環境
使用したのは以下のコード、ブラウザは
「Chrome バージョン: 104.0.5112.101(Official Build) (x86_64)]
を使用しました。以下のコードはVue.jsで記載しています。動作確認する場合は、「npm init nuxt-app」でプロジェクトを作成して、index.vueを下記コードに入れ替えてもらえれば動作します。
<template>
<div id="app">
<button v-on:click="showMessage">ボタン</button>
<p>{{ msg }}</p>
</div>
</template>
<script>
var parser = require("ua-parser-js");
export default {
data() {
return {
name: "app",
msg: "",
currentfocus: false,
};
},
created: function () {
window.addEventListener("focus", this.focus);
window.addEventListener("blur", this.blur);
},
destroyed: function () {
window.removeEventListener("focus", this.focus);
window.removeEventListener("blur", this.blur);
},
methods: {
async showMessage() {
var ua = parser(window.navigator.userAgent);
if (ua.browser.name === "Chrome" || ua.browser.name == "Edge") {
let newmsg = "";
/* setInterval(async () => {
try {
if (this.currentfocus == true) {
newmsg = await navigator.clipboard.readText();
if (newmsg != this.msg) {
this.msg = newmsg;
}
}
} catch (err) {
console.log(err);
}
}, 5000);*/
await navigator.clipboard.writeText("テスト書き込み");
this.msg = "書き込み完了";
}
},
focus() {
this.currentfocus = true;
},
blur() {
this.currentfocus = false;
},
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
以前使用したreadText()はコメント化しており、writeText()の処理は追加しています。今回はwriteなのでタイマー処理も外しました。
検証結果・対応策
結果は・・・
「パーミッション無しで書き込み成功しました」
readText()のときも初回のパーミッションだけで自由に使えてしまったので、違和感はあったのですが、writeText()だとユーザが知らない間にclipboardに自由に書き込めてしまいますね。
「readText()の時もパーミッションを取らないのでは」というコメントもあったのですが、動作確認した限りでは、許可が必要でした。
以下Chomeがクリップボードへのアクセスの際にパーミッションを取得する際のスクリーンショットです。
ブラウザ利用時にこのダイアログが出たらWebサイトからクリップボードへアクセスしてるので気をつけましょう!
今のところ本現象を防ぐにはjavascriptのオフしか対応方法を思いつかないのですが、writeであればそこまで大きな問題とはならない?という判断なのかもしれません。