Chrome ExtensionsとChrome Apps

(2019-02-19)

Chrome Extrnsions

ツールバーに表示され、ChromeのAPIを呼んで色々できる拡張機能で、manifestとhtml, js, cssなどから構成される。 開発中はディレクトリごとchrome://extensions/から読み込むとインストールでき、ツールバーにアイコンが表示される。

test-chrome-extension

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のリスナー内で制御する。

インストール時や更新時など必要なときにロードされるスクリプト。イベントリスナーはここで設定する。

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

Chrome Apps

Extensionと同じようなmanifestとhtml, js, cssなどで構成されるネイティブアプリ。 かつてはクロスプラットフォームで動かすことができたが、 Webアプリで事足りるようになったということで、Chrome OS以外でのサポートが切られてしまった。 そのChromeOSでもAndroidLinuxのアプリがサポートされつつあって、いつまでサポートされるかは分からない。

ということで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();
  }
});