Chrome Extrnsions
ツールバーに表示され、ChromeのAPIを呼んで色々できる拡張機能で、manifestとhtml, js, cssなどから構成される。 開発中はディレクトリごとchrome://extensions/から読み込むとインストールでき、ツールバーにアイコンが表示される。
manifest.json
manifest_version, name, versionと、brower_actionかpage_actionのどちらかはRequired。
{
"manifest_version": 2,
"name": "test-chrome-extension",
"version": "1.0",
"icons": {
"128": "images/icon-128.png"
},
"page_action": {
"default_icon": {
"32": "images/icon-32.png"
}
},
"options_page": "options.html",
"background": {
"scripts": [
"background.js"
],
"persistent": false
},
"permissions": [
"declarativeContent",
"storage"
],
"content_security_policy": "script-src 'self'; object-src 'self'"
}
常にツールバーに表示されているbrowser_actionに対して、限られたページでのみ有効なAction。 有効かどうかは declarativeContent.onPageChangedの conditionsや、tags.onUpdatedのリスナー内で制御する。
- options_page: “拡張機能のオプション"で表示されるページ
- background
インストール時や更新時など必要なときにロードされるスクリプト。イベントリスナーはここで設定する。
chrome.runtime.onInstalled.addListener(() => {
chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
chrome.declarativeContent.onPageChanged.addRules([
{
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostEquals: 'www.google.com', schemes: ['https'] },
})
],
actions: [new chrome.declarativeContent.ShowPageAction()]
}
]);
});
});
chrome.pageAction.onClicked.addListener((tab) => {
console.log("Clicked");
});
chrome.runtime.onSuspend.addListener(() => {
alert("Unloading.");
});
ここで出力したログはchrome://extensions/の"バックグラウンドページ"から確認でき、 https://www.google.comを開いてアイコンを押すと"Clicked"が出力される。
storageなどのAPIを使えるようにしたり、 HTML5のgeolocationをユーザーの許可なしに使えるようにするといった権限。 permissonが足りないと次のようなエラーが出る。
Error in event handler: TypeError: Cannot read property 'onPageChanged' of undefined
- content_security_policy: 主にXSS対策のためのリソースのドメイン制限などの記述
Chrome Apps
Extensionと同じようなmanifestとhtml, js, cssなどで構成されるネイティブアプリ。 かつてはクロスプラットフォームで動かすことができたが、 Webアプリで事足りるようになったということで、Chrome OS以外でのサポートが切られてしまった。 そのChromeOSでもAndroidやLinuxのアプリがサポートされつつあって、いつまでサポートされるかは分からない。
ということでChrome OS以外ではストアから入れることはできないが、MacのChrome 72.0.3626.109時点では Extensionと同様にchrome://extensions/から読み込むとChromeアプリとして認識された。
manifest.json
Extensionのmanifestと比べると、backgroundがappの中に入りRequiredになっていたり、 socketsやbluetoothといったデバイスに関するものや、 kioskモードの項目がある。
{
"name": "test-app",
"version": "1.0",
"icons": {
"128": "images/icon-128.png"
},
"app": {
"background": {
"scripts": ["background.js"]
}
},
"bluetooth": {
"low_energy": true,
"uuids": ["180a"]
}
}
制約
Chrome Appsではセキュリティモデルによって、 外部のコンテンツをiframeで埋め込んだり、インラインスクリプトやeval()を実行することができない。
Refused to frame 'https://*****' because it violates the following Content Security Policy directive: "frame-src 'self' blob: filesystem: data: chrome-extension-resource:".
そのためiframeの代わりにwebviewを使う必要がある。
<webview id="foo" src="https://www.google.com/" style="width:640px; height:480px"></webview>
webviewではプロセスが分離され、permissionもイベントリスナーで許可しないと付与されない。
const webview = document.getElementById("foo");
webview.addEventListener('permissionrequest', function(e) {
if (e.permission === 'media') {
e.request.allow();
}
});