先日作成した Chrome拡張機能 が http
サイト では上手く動かないことに気付いたので修正しました。
早速作成した Chrome拡張機能 を運用し始めたのですが、一部のサイトでは次のエラーを出力して上手く動かないことが分かりました。
Unchecked runtime.lastError: The message port closed before a response was received.
いくつかのサイトを試験した結果、 http
サイト ではこのエラーが出力されることが分かりました。
そこで調べてみると……
WebExtension の場合、clipboardRead や clipboardWrite パーミッションを要求することで clipboard.readText() や clipboard.writeText() を使うことができます。HTTPサイトに適用されたコンテンツスクリプトは、Clipboard オブジェクトにアクセスすることはできません。
ビンゴ。 http
サイト の Content Script では navigator.clipboard
へアクセスできないようです。
navigator.clipboard
へアクセスできないとなると、手っ取り早いのは document.execCommand('copy')
によるクリップぼ度貼り付けです。
今回は http
サイト という基本レガシーと想定される環境への対処なので、 document.execCommand('copy')
で妥協しておきますかね……という感じです。
- chrome.tabs.sendMessage(tab.id, clipText, function(response) {
- console.log(response.value);
+ chrome.tabs.sendMessage(
+ tab.id,
+ {
+ text: clipText,
+ url: tab.url,
+ },
+ function(response) {
+ console.log(response.value);
chrome.tabs.sendMessage()
の第二引数は元はシンプルにクリップボードに貼り付けたいテキストを投げていましたが、今回は http://
か https://
かの判定をしたかったのでURLのみのシンプルなテキストも送ることにしました。そこで、Stringだった引数をObjectに変更。
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
// メッセージとして送信されたクリップボードに貼り付けたいテキストをそのままレスポンスに設定して返却
- navigator.clipboard.writeText(request);
+ if(request.url.toLowerCase().startsWith('https://')) {
+ navigator.clipboard.writeText(request.text);
+ }
+ else {
+ const inputID = 'chromeExtension-emeraldIsle-clipText';
+ console.log(document.querySelector(`#${inputID}`))
+ if(document.querySelector(`#${inputID}`) === null) {
+ const $input = document.createElement('input');
+ $input.setAttribute('type', 'text');
+ $input.setAttribute('id', inputID);
+ $input.setAttribute('style', 'position: absolute; left: -100vw; top: 0');
+ document.body.appendChild($input);
+ }
+ const $inputDom = document.querySelector(`#${inputID}`);
+ $inputDom.value = request.text;
+ $inputDom.select();
+ document.execCommand('copy');
+ }
sendResponse({
- value: request,
+ value: request.text,
});
+ return true;
});
content Scripts 側を大改造。元々は navigator.clipboard.writeText(request);
のみのシンプルな内容でしたが、次のように処理を変更。
https://
(大文字小文字区別せず) で始まるかどうかを判定navigator.clipboard.writeText(request.text);
で貼り付けinput
要素 を追加input
要素 を取得、値にクリップボードに貼り付けたいリンク文字列をセットdocument.execCommand('copy')
でクリップボードにコピーこれで http
サイト でもリンク文字列をクリップボードに貼り付けられるようになりました。
any
だった。
一瞬 Background Page を作ってそのテキストボックスにいったん貼り付けて、その値を取得する方法を考えました。
今回 Webpack 使用だったので html-loader
案件か、と思いましたが、回避しました。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント