ウェブプッシュを使用する

拡張機能では、任意の Push プロバイダを使用してプッシュ通知とメッセージを送信できます。Push API からのプッシュは、受信するとすぐに Service Worker によって処理されます。Service Worker が一時停止されている場合、Push によって再開されます。拡張機能で使用するプロセスは、オープン ウェブで使用する場合とまったく同じです。

Push API を使用する権限を取得する

通常のウェブサイトで Push サーバーを登録すると、ユーザーに権限を付与するか拒否するかを尋ねるメッセージが表示されます。拡張機能を使用すると、このプロンプトは表示されません。拡張機能で Push API を使用するには、manifest.json で notifications 権限を設定する必要があります。

  {
    "manifest_version": 3,
    ...
    "permissions": ["notifications"]

この権限がない場合、registration.pushManager とのやり取りはすべて直ちにエラーとなり、ユーザーが権限を拒否した場合と同じ結果になります。また、notifications 権限があると、インストール時に権限に関する警告が表示されることにも注意してください。また、ユーザーが新しい権限のリクエストを承認するまで、既存のインストールについても拡張機能が無効になります。この処理方法について詳しくは、権限に関する警告のガイドをご覧ください。

プッシュ プロバイダとプッシュ サービス

manifest.json に権限を追加したら、バックエンドと拡張機能の間の接続を構成する必要があります。この接続は、プッシュ プロバイダとプッシュ サービスの 2 つの部分で構成されています。プロバイダは、Push サービスにメッセージを送信するために使用する SDK です。さまざまなオプションがあり、どのプッシュ プロバイダも Push API で使用できます(ただし、統合を簡単にする SDK を提供していない場合があります)。プロバイダの SDK を試して、何ができるかを確認する必要があります。プッシュ サービスは、エンドユーザーのデバイスが登録されているサービスです。これにより、プッシュ プロバイダから送信されたプッシュ メッセージを通知できます。これは個々のブラウザにハードコードされているため、ユーザーが制御することはできません。Chrome の場合、Firebase Cloud Messaging が Push サービスです。Chrome ユーザーにプッシュされるメッセージはすべて、このサーバーを経由します。

プッシュ プロバイダの自己ホスティング

任意のプッシュ プロバイダを使用できますが、Service Worker で動作する SDK を提供しているプロバイダはすべてではありません。実行に問題がある場合は、プロバイダに問い合わせる必要があります。ただし、パブリック プロバイダを使用する必要はありません。web-push などのライブラリを使用すると、独自のバックエンドをホストできます。

このライブラリは web-push-codelab.glitch.me でテストできます。具体的には、ブラウザでプッシュ サブスクリプションを生成するために、プッシュ サーバーの VAPID 公開鍵をコピーする必要があります。この公開鍵は実際には base64 でエンコードされたバイナリ値であり、ブラウザの Push manager に登録するには、デコードして Uint8Array に変換する必要があります。このロジックを実行するためのライブラリはありますが、必要なのは次のものだけです。

function urlB64ToUint8Array(base64String) {
  const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
  const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');

  const rawData = atob(base64);
  const outputArray = new Uint8Array(rawData.length);

  for (let i = 0; i < rawData.length; ++i) {
    outputArray[i] = rawData.charCodeAt(i);
  }
  return outputArray;
}

指定された値は Push マネージャーに渡されます。

const SERVER_PUBLIC_KEY = '_INSERT_VALUE_HERE_';
const applicationServerKey = urlB64ToUint8Array(SERVER_PUBLIC_KEY);

async function subscribe() {
  try {
    let subscription = await self.registration.pushManager.subscribe({
      userVisibleOnly: true,
      applicationServerKey
    });

    console.log(`Subscribed: ${JSON.stringify(subscription,0,2)}`);

    return subscription
  } catch (error) {
    console.error('Subscribe error: ', error);
  }
}

const subscription = await subscribe();

subscribe 関数は、Push サーバーのメタデータを含むオブジェクトである PushSubscription を返します。web-push-codelab.glitch.me を使用しているので、この値をページの [Push Subscription] 部分にコピーする必要があります。

PushSubscription を取得したら、拡張機能の Service Worker でプッシュ メッセージのリスナーを登録できます。

self.addEventListener('push', function (event) {
  console.log(`Push had this data/text: "${event.data.text()}"`);
});

リスナーを配置したら、web-push-codelab.glitch.me でメッセージを送信できます。メッセージはサービス ワーカーのコンソールに記録されます。

オープン ウェブ標準であるため、Chrome のブログなど、ウェブプッシュの実装方法に関する既存のドキュメントが多数あります。ここで説明した例の完全なバージョンは、拡張機能のサンプル リポジトリで入手できます。

サイレント プッシュ

Chrome 88 で Manifest v3 が導入されて以来、Manifest v3 拡張機能でプッシュ通知を受け取ることができるようになりました。ただし、通知には ウェブ通知などのユーザーに表示されるプロンプトを表示するという要件が常にありました。このため、不要な情報をユーザーに表示せずに、コマンドやデータ更新を拡張機能にプッシュしたい場合には、あまり役に立ちませんでした。Chrome 121 以降では、拡張機能で userVisibleOnlyfalse に設定できます。ユーザーにサイレント プッシュ通知を送信できるようになりました。これを使用するには、pushManager.subscribe を呼び出すときに userVisibleOnlyfalse に設定します。

let subscription = await self.registration.pushManager.subscribe({
  userVisibleOnly: false,
  applicationServerKey
});