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

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

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

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

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

この権限がない場合、registration.pushManager を操作するとすぐにエラーが発生します。これは、ユーザーが権限を拒否した場合と同じ結果です。また、notifications 権限を使用すると、インストール時に権限に関する警告が表示されます。また、ユーザーが新しい権限リクエストを承認するまで、Chrome は既存のインストールの拡張機能を無効にします。詳しくは、権限に関する警告ガイドをご覧ください。

Push プロバイダと Push サービス

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

push プロバイダのセルフホスト

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

このライブラリは、web-push-codelab.glitch.me を使用してテストできます。具体的には、ブラウザで push サブスクリプションを生成するには、push サーバーの VAPID 公開鍵をコピーする必要があります。この公開鍵は実際には base64 でエンコードされたバイナリ値であり、ブラウザのプッシュ マネージャーに登録するには、デコードして 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 サブスクリプション] 部分にコピーする必要があります。

PushSubscription を作成したら、拡張機能の Service Worker に push メッセージのリスナーを登録できます。

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

リスナーが設定されたら、web-push-codelab.glitch.me でメッセージを送信できます。メッセージは Service Worker のコンソールにログに記録されます。

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

サイレント プッシュ

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

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