どのようにコンテンツのスクリプト、ポップアップ、およびバックグラウンドのブラウザの拡張機能の開発の間で通信する
25128 ワード
ブラウザ拡張機能の異なる部分の間のメッセージパッシングは、ブラウザの拡張機能の開発から始まるとき、最も混乱している部分です.この投稿は、コンテンツのスクリプト、背景、およびポップアップ(ブラウザ動作)の間で通信するために、どのように私のWeb拡張モジュールを構成するかについてです.
これらは我々が使用する部分です. ファイル内で使用するメッセージのIDを作成します.通常のオブジェクトリテラルまたは マッピングを作成する メッセージリスナーを登録します.アイテムのループを
コードを書きましょう
完成したコードはweb-extension-communication-blog-post . 私はあなたのリンクを開いて、私と一緒に従ってください.また、FirefoxとChromeのAPIの違いに対処する必要がないので、ポリフィルを使用します.また、PolyFillは両方のFirefoxとChromeのための見込みベースAPIを許します.使用中webextension-polyfill-ts Mozilla ' sのためのタイプスクリプトラッパーですwebextension-polyfill .
私たちのメッセージは簡単になります.コンテンツスクリプトと背景の間に「hi」または「bye」を交換します.
まず、コンテンツスクリプトと背景の間にメッセージを送信するために使用できるユーティリティ関数を2つ書きます.
手順1で、各タイプのメッセージのIDを作成します.私はタイプスクリプトを使っています
バックグラウンドからのコンテンツスクリプトへのメッセージの送信も、コンテンツスクリプトのタブIDを渡す必要があることに似ています.それはあなたが見る最初のパラメータです
メッセージリスナーの登録
ステップ2と3で話したメッセージリスナーを登録します.このコードは、コンテンツスクリプトと背景の両方に似ています.登録します
結論
我々は、メッセージングのほとんどを抽象化しました
このコードはFirefoxとすべてのクロムベースのブラウザで動作します.単にメッセージを送信して
このように解決しようとしている他の方法がありますwebext-redux 拡張子の異なる部分の間の状態を管理することとともにメッセージを渡すための賢い方法です
このブログ記事のために構築したサンプル拡張子をインストールできますhere .
良い一日を!👋
これらは我々が使用する部分です.
enum
を使用する場合.Map<MessageID, callback>
そして、そのIDを持つメッセージが到着したときに実行するコールバックで、ステップ1で作成したメッセージIDを修正します.Map
ステップ2で作成したリスナーを追加しますvalue
各キーについてMessageID
). コードを書きましょう
完成したコードはweb-extension-communication-blog-post . 私はあなたのリンクを開いて、私と一緒に従ってください.また、FirefoxとChromeのAPIの違いに対処する必要がないので、ポリフィルを使用します.また、PolyFillは両方のFirefoxとChromeのための見込みベースAPIを許します.使用中webextension-polyfill-ts Mozilla ' sのためのタイプスクリプトラッパーですwebextension-polyfill .
私たちのメッセージは簡単になります.コンテンツスクリプトと背景の間に「hi」または「bye」を交換します.
まず、コンテンツスクリプトと背景の間にメッセージを送信するために使用できるユーティリティ関数を2つ書きます.
// Messenger.ts
import { browser } from "webextension-polyfill-ts";
const Messenger = {
/**
* Send a message to Background script
*
* @param {BackgroundMessage} type Background Message Type
* @param {*} [data=null]
* @return {*}
*/
async sendMessageToBackground(type, data = null) {
try {
const response = await browser.runtime.sendMessage({ type, data });
return response;
} catch (error) {
console.error("sendMessageToBackground error: ", error);
return null;
}
},
/**
* Send a message to Content Script of a Tab
*
* @param {number} tabID Tab ID
* @param {ContentScriptMessage} type
* @param {*} [data=null]
* @return {*}
*/
async sendMessageToContentScript(tabID, type, data = null) {
try {
// Notice the API difference - browser.tabs to send to content script but browser.runtime to send to background.
const response = await browser.tabs.sendMessage(tabID, { type, data });
console.log("response:", response);
return response;
} catch (error) {
console.error("sendMessageToContentScript error: ", error);
return null;
}
},
};
私は、我々が常に投げる必要がないので、別々のファイルにこれらの2つの機能を置くのが好きですbrowser.tabs
or browser.runtime
どこでもAPI.我々はクリーンなコードを得るMessenger.sendMessageToBackground
and Messenger.sendMessageToContentScript
関数.手順1で、各タイプのメッセージのIDを作成します.私はタイプスクリプトを使っています
enums
彼らは簡単に機能を入力するが、同様に単純なオブジェクトを使用することができます.IDは- 1 , 2 ,// messages.ts
export enum ContentScriptMessages {
SAY_HELLO_TO_CS,
SAY_BYE_TO_CS,
}
export enum BackgroundMessages {
SAY_HELLO_TO_BG,
SAY_BYE_TO_BG,
}
コンテンツスクリプトやポップアップからバックグラウンドスクリプトと話をする必要があるときはいつでもMessenger.sendMessageToBackground(BackgroundMessages.SAY_HELLO_TO_BG, {message: "Hey Background"})
.バックグラウンドからのコンテンツスクリプトへのメッセージの送信も、コンテンツスクリプトのタブIDを渡す必要があることに似ています.それはあなたが見る最初のパラメータです
Messenger.sendMessageToContentScript(tabID, ContentScriptMessages.SAY_HELLO_TO_CS, {message: "Hey Content Script!"})
関数.メッセージリスナーの登録
ステップ2と3で話したメッセージリスナーを登録します.このコードは、コンテンツスクリプトと背景の両方に似ています.登録します
ContentScriptMessages
コンテンツスクリプト初期化とBackgroundMessages
バックグラウンド初期化.// content-script.ts
// Install webextension-polyfill for JavaScript based projects
import { browser } from "webextension-polyfill-ts";
import { BackgroundMessages, ContentScriptMessages } from "./messages";
import Messenger from "./Messenger";
class ContentScript {
requests = new Map();
async receiveHello(sender, data) {
console.log(`receiveHelloFromBackground: `, data);
}
async receiveBye(sender, data) {
console.log(`receiveByeFromBackground: `, data);
}
async sayHelloToBackground() {
const response = await Messenger.sendMessageToBackground(
BackgroundMessages.SAY_HELLO_TO_BG,
{ message: "Hello Background!!!" }
);
console.log("Background Response: ", response);
}
async sayByeToBackground() {
await Messenger.sendMessageToBackground(BackgroundMessages.SAY_BYE_TO_BG, {
message: "Bye Background!!!",
});
}
registerMessengerRequests() {
this.requests.set(ContentScriptMessages.SAY_HELLO_TO_CS, this.receiveHello);
this.requests.set(ContentScriptMessages.SAY_BYE_TO_CS, this.receiveBye);
}
listenForMessages() {
browser.runtime.onMessage.addListener((message, sender) => {
const { type, data } = message;
return this.requests.get(type)(sender, data);
});
}
init() {
// 1. Create a mapping for message listeners
this.registerMessengerRequests();
// 2. Listen for messages from background and run the listener from the map
this.listenForMessages();
}
}
new ContentScript().init();
//background.ts
import { browser, Runtime } from "webextension-polyfill-ts";
import { BackgroundMessages, ContentScriptMessages } from "./messages";
import Messenger from "./Messenger";
import { IMessage, MessageListener } from "./types";
class Background {
requests = new Map<BackgroundMessages, MessageListener>();
async receiveHello(sender: Runtime.MessageSender, data: IMessage<any>) {
console.log("receiveHelloFromContentScript: ", data);
return {
message: "Hey there!!!",
};
}
async receiveBye(sender: Runtime.MessageSender, data: IMessage<any>) {
console.log("receiveByeFromContentScript: ", data);
return {
message: "Bye there!!!",
};
}
async sayHelloToContentScript(tabID: number) {
await Messenger.sendMessageToContentScript(
tabID,
ContentScriptMessages.SAY_HELLO_TO_CS,
{ message: "Hello from BG!!!" }
);
}
async sayByeToContentScript(tabID: number) {
await Messenger.sendMessageToContentScript(
tabID,
ContentScriptMessages.SAY_BYE_TO_CS,
{ message: "Bye from BG!!!" }
);
}
registerMessengerRequests() {
this.requests.set(BackgroundMessages.SAY_HELLO_TO_BG, this.receiveHello);
this.requests.set(BackgroundMessages.SAY_BYE_TO_BG, this.receiveBye);
}
listenForMessages() {
browser.runtime.onMessage.addListener((message, sender) => {
const { type, data } = message;
return this.requests.get(type)(sender, data);
});
}
// Example: Send message to content script of active tab
sendHelloToActiveTab() {
browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => {
tabs.forEach((tab) => {
this.sayHelloToContentScript(tab.id);
});
});
}
init() {
// 1. Create a mapping for message listeners
this.registerMessengerRequests();
// 2. Listen for messages from background and run the listener from the map
this.listenForMessages();
}
}
new Background().init();
私たちはmessages.ts
and Messenger.ts
ポップアップからも.ポップアップはすべての時間を開くことはありませんので、我々はそこにメッセージリスナーを追加する必要はありません.私は、使用を好むMessenger.sendMessageToBackground
とポップアップの戻り値を使用します.結論
我々は、メッセージングのほとんどを抽象化しました
messages.ts
and Messenger.ts
. 新しいタイプのメッセージを追加するたびにenum
(またはオブジェクトを使用した場合にキーを追加する)messages.ts
そして、内容スクリプトまたはバックグラウンドでリスナーを加えますregisterMessengerRequests
関数.このコードはFirefoxとすべてのクロムベースのブラウザで動作します.単にメッセージを送信して
await
他の側がリスナーから何かを返すならば、応答のために.Mozillaのおかげでwebextension-polyfill 我々はクロスブラウザのサポートを取得し、ChromeのAPIのコールバックバージョンに対処する必要はありません.このように解決しようとしている他の方法がありますwebext-redux 拡張子の異なる部分の間の状態を管理することとともにメッセージを渡すための賢い方法です
redux
ウェイ.しかし、私はそれが既存の複雑さを解決して、反応だけで働く試みで、さらなる冗長なAPIを加えると感じます.お気軽にそのリポジトリをチェックしてお客様の要件に合う場合.このブログ記事のために構築したサンプル拡張子をインストールできますhere .
良い一日を!👋
Reference
この問題について(どのようにコンテンツのスクリプト、ポップアップ、およびバックグラウンドのブラウザの拡張機能の開発の間で通信する), 我々は、より多くの情報をここで見つけました https://dev.to/saisandeepvaddi/how-to-communicate-between-content-script-popup-and-background-in-browser-extension-development-31eoテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol