Chrome 拡張機能で PWA と IWA を接続する

Demián Renzulli
Demián Renzulli

ウェブ デベロッパーは、プログレッシブ ウェブアプリ(PWA)など、可能な限り信頼性の低いセキュリティ モデルを使用してアプリケーションを設計することが効果的な手法です。このアプローチにより、リーチを最大化し、管理する必要があるセキュリティ オーバーヘッドを最小限に抑え、デベロッパーとユーザーの両方に最大限の柔軟性を提供できます。ただし、ウェブはデフォルトで安全になるように設計されているため、その保守的なセキュリティ モデルにより、オペレーティング システムや特定の強力なデバイス API へのアクセスが自然に制限されます。

独立したウェブアプリ(IWA)は、ウェブ プラットフォーム上に構築された、分離され、バンドルされ、バージョン管理され、署名された、信頼性の高いアプリケーション モデルを提供することで、この問題を解決します。ただし、IWA に移行する前に、PWA を Chrome 拡張機能に接続するという、より段階的な方法を検討することをおすすめします。管理対象 ChromeOS 環境(管理対象ユーザー セッション、管理対象ゲスト セッション(MGS)、キオスクモードなど)で利用できるこの手法により、アプリは安全なメッセージ パッシングを通じて下位レベルの拡張機能 API を使用できます。次の図は、この段階的なアプローチを示しています。標準的なウェブ アプリケーションから始まり、インストール可能な PWA になるための機能を追加し、最後に PWA と Chrome 拡張機能のパスを調べて追加の API を利用できるようにします。

イメージ
プログレッシブ エンハンスメントのパス。インストール可能な PWA とコンパニオン Chrome 拡張機能を組み合わせることで、デベロッパーはウェブの安全な環境と下位レベルの OS およびデバイス機能のギャップを埋めることができます。

Chrome 拡張機能 API を使用しても、Controlled FrameDirect Sockets API など、高度な機能が利用できない場合は、独立したウェブアプリ(IWA)に移行するのが最善の方法です。ただし、IWA は強力な新しいウェブ機能を有効にしますが、キオスクモードで ChromeOS デバイスを再起動するための chrome.runtime.restart() など、Chrome 拡張機能専用の特定のデバイスレベルの API が必要な場合もあります。幸いなことに、PWA とまったく同じアプローチを使用して、IWA を Chrome 拡張機能に接続できます。この手法については、次の手順で説明します。

実装の手順

コンパニオン拡張機能をデプロイする

拡張機能は Chrome 管理コンソールからデプロイされます。対象環境に応じて、対応するセクションで設定します(たとえば、キオスクモードの場合は [デバイス] > [Chrome] > [アプリと拡張機能] > [キオスク] に移動します。また、[ユーザーとブラウザ] または [管理対象ゲスト セッション] の各タブでも設定できます)。拡張機能は、一般公開されているリンクでセルフホストするか、Chrome ウェブストアで直接ホストできます。拡張機能の管理に関する詳細な手順については、公式ドキュメントをご覧ください。

メッセージ パッシングを実装する

拡張機能の設定

ウェブアプリからのメッセージを受信して応答するには、クライアント(ウェブアプリ)からメッセージが届くのをリッスンし、それらのリクエストを対応する API 呼び出しにプロキシするバックグラウンド スクリプトを公開します。次の例では、ウェブアプリが methodNamecallRestart を含むカスタム メッセージ オブジェクトを送信したときに、ChromeOS デバイスを再起動するリクエストがプロキシされます。

Background.js

// message handler - extension code
chrome.runtime.onMessageExternal.addListener(function (request, sender, sendResponse) {
  if (request.methodName == 'callRestart') {
    chrome.runtime.restart();
  }
});

拡張機能のマニフェストは、externally_connectable⁠⁠ キーを使用して、拡張機能への外部関数呼び出しを許可するように構成できます。このキーは、拡張機能のメソッドの呼び出しを許可するサイトと拡張機能を指定します。Chrome 拡張機能とマニフェスト v3 について詳しくは、公式ドキュメントをご覧ください。

プログレッシブ ウェブアプリ(PWA)から接続する場合は、アプリがホストされている標準の HTTPS ドメインを matches 配列にリストします。キオスクモードで実行される PWA 用に構成されたマニフェストの例を次に示します。

Manifest.json

{
  "manifest_version": 3,
  "name": "Restart your kiosk app",
  "version": "1.0",
  "description": "This restarts your ChromeOS device.",
  "background": {
    "service_worker": "background.js"
  },
  "externally_connectable": {
    "accepts_tls_channel_id": false,
    "matches": [
      "*://developer.chrome.com/*"
    ]
  }
}

独立したウェブアプリ(IWA)から接続する場合、メカニズムはまったく同じですが、URL スキームが変更されます。IWA は安全にパッケージ化され、標準のウェブサーバーで実行されないため、独自のプロトコルを使用します。isolated-app:// スキームを使用して IWA のオリジンを追加する必要があります。

Manifest.json

{
  "manifest_version": 3,
  "name": "IWA Companion Extension",
  "version": "1.1",
  "description": "Companion extension for the IWA",
  "background": {
    "service_worker": "/scripts/background.js"
  },
  "externally_connectable": {
    "matches": [
      "isolated-app://*/*"
    ]
  }
}

これは、PWA または IWA からのメッセージをリッスンするために拡張機能で必要な最小限のコードです。

PWA と IWA の設定

ウェブアプリから拡張機能を呼び出すには、静的拡張機能 ID を知っておく必要があります。この ID は、Chrome 拡張機能をインストールする際に表示される chrome://extensions ページで確認できます。また、拡張機能のアップロード後に Chrome ウェブストアで確認することもできます。これにより、ウェブアプリは通信する拡張機能を正確に指定できます。その後、chrome.runtime.sendMessage を呼び出し、拡張機能に送信するメッセージとともに拡張機能 ID を渡します。

const STATIC_EXTENSION_ID = 'abcdefghijklmnopqrstuvwxyz';
// found from chrome extensions page of chrome web store.
const callExtensionAPI = function (method) {
  chrome.runtime.sendMessage(STATIC_EXTENSION_ID, {
    methodName: method,
  });
};
callExtensionAPI('callRestart');

ウェブアプリを拡張機能に接続してメッセージを渡す方法について詳しくは、拡張機能のドキュメント⁠⁠をご覧ください。

デモ

この実装の動作を確認するには、IWA Kitchen Sink リポジトリをご覧ください。このプロジェクトは、さまざまな独立したウェブアプリ機能の包括的なプレイグラウンドとして機能し、Direct Sockets や Controlled Frame などの高信頼性 API のデモを備えています。また、IWA と Chrome 拡張機能の接続の完全な動作例も提供します。このリポジトリには、安全なメッセージ パッシングを使用して拡張機能専用のメソッドをトリガーする方法を示すサンプル コンパニオン拡張機能と専用のウェブ インターフェースが含まれています。たとえば、独立したウェブアプリから chrome.identity.getProfileUserInfo() API を使用して、ユーザーのプロフィール情報を取得するテストを行うことができます。

まとめ

ウェブ アプリケーションを Chrome 拡張機能に接続すると、ネイティブのようなデバイス機能を安全かつ段階的に利用できるようになります。アプリのアーキテクチャを設計する際は、次の重要なポイントに留意してください。

  1. ウェブから始める: リーチを最大化し、セキュリティのオーバーヘッドを最小限に抑えるには、デフォルトで PWA を使用します。
  2. 拡張機能でギャップを埋める: OS レベルの機能(キオスクモードでのデバイスの再起動など)を深く統合するには、コンパニオン Chrome 拡張機能をデプロイし、安全なメッセージ パッシングを使用してアプリケーションに接続します。
  3. 必要な場合にのみ IWA にアップグレードする: Direct Sockets、Controlled Frame、その他の IWA 専用 API などの信頼性の高い API が必要な場合は、独立したウェブアプリを使用します。