初めてChrome拡張を作成したのですが、概念が分かりにくかったので覚書。
拡張機能としてはフェーズが3種類あります。
ページ内スクリプトに最も近いContentScript、
クリック時にのみ起動し、対象のサイトに直接は介入できないPageAction / BrowserAction、
永続化されて存在するBackgroundPage
Content Script
content_scriptのmanifestファイルを見てみましょう。
細かい項目は省きますが、jsとcssを対象のサイトに挿入できます。
{
"manifest_version": 2,
"name": "hoge",
"version": "0.1.0",
"description": "",
"content_scripts": [
{
"run_at": "document_end",
"matches": ["http://*/*", "https://*/*"],
"js": ["index.js"],
"css": ["index.css"]
}
]
}
ただ、この言い方は語弊があります。冒頭でも「ページ内スクリプトに最も近い」と書いたとおり、このScriptの立ち位置はもう少し複雑です。
実は対象サイトに元々存在するjsと並列に対象サイトに打ち込まれるわけではありません。
挿入されるjs群は元のサイトとは独立した空間で実行されます。
一方で、jsが扱うdocument(html)は対象のサイトとなります。
htmlを通して両者は結合しています。
どういうことかというと、挿入したjsは対象サイトから独立しているため、対象のサイト内に埋め込まれているjsの変数やメソッドを直接扱ったりはできません。あれ?思ってたのと違う!と思われるかもしれませんが、そうなのです。
しかし、強引な手法で相手先のjs空間と同じ空間にjsを埋め込むことができます。それはscriptタグを相手のhtmlに埋め込むことです。こうすることによって対象サイトのjs空間内に直接jsを埋め込み実行できます。
この辺りがかなりトリッキーな構造になっているため、ちゃんと理解しないと思った動作ができません。
またContentScriptはBrowserが持つAPIのフル機能は使えません。いわゆるサイト内jsと同じレベルでしか扱えないため、後述の方法(BrowserActionやBackgroundPage)を併用して高度な機能を実現します。
Page Action / Browser Action
ContentScriptでは実行できないブラウザのAPIを利用したい時かつViewが必要な場合に使います。
生存期間など細かな違いはあると思いますが、後述のBackgroundPageと実質的に同じで、BackgroundPageにviewを持たせたいときに利用する、と認識しています。
PageActionを設定すると、画面右上のツールバー上に表示されるようになり、クリックすると設定したhtmlを表示できます。
私は使ってないので正確かどうか保証しかねますが、Page Action / Browser Actionともに同じものです。デフォルトでONなのがBrowserActionで、デフォルトでOFFなのがPageActionと思っています。
BackgroundPage / EventPage
APIのフル機能を使えるScriptになります。
BackgroundPageは永続化し、Chromeの起動から終了まで生存し続けてリソースを食うため、EventPageの利用が推奨されています。両者の違いはBackground常駐か、イベントトリガーで必要なときのみリソースを取るかです。
EventPageにすると永続化せずに定期的に終了されるため、データを貯めておくような処理の場合は終了前にChrome内のstorageに書き出す、といった処理が必要になります。
逆に言うとその程度なので、基本的にEventPageを利用します。
{
"manifest_version": 2,
"name": "hoge",
"version": "0.1.0",
"description": "",
"content_scripts": [
{
"run_at": "document_end",
"matches": ["http://*/*", "https://*/*"],
"js": ["index.js"],
"css": ["index.css"]
}
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions": ["downloads"],
"icons": {
"128": "hoge.png"
}
}
利用する場合はbackgroundにjsを指定し、persistentにfalseを指定します。
persistent: trueの場合はBackgroundPage(永続化)、
persistent: falseの場合がEventPage
になります。
permissionsという項目も増えています。
これは拡張機能に利用させるChromeAPI群を指定します。
tabsだったり、downloadsだったり、使いたい機能を設定します。
background.jsとcontent_script.jsとは別の世界線で実行されているため、直接相互のメソッドを呼んだりはできません。
chrome.runtime系のメソッドにて通信します。
一般的なのはこんな感じです。
background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.download_url) {
chrome.downloads.download({
url: message.download_url,
filename: message.filename,
saveAs: false,
});
}
sendResponse('download called');
});
content_script.js
function download(url, filename) {
chrome.runtime.sendMessage(
{
download_url: url,
filename: filename,
},
function (responseMessage) {
console.log(responseMessage);
}
);
}
content_script側からchrome.runtime.sendMessageでbackground.jsに向けてメッセージを飛ばします。
background.js側ではmessageイベントを購読しておき、目的のイベントが飛んできた場合に発火させます。レスポンスを返したい場合はsendResponseに適当なオブジェクトを詰めて返します。
コメント