説明
chrome.mimeHandler API を使用して、サードパーティ拡張機能の MIME タイプのストリームを処理します。
対象
マニフェスト
コンセプトと使用方法
これまで、特定のドキュメント タイプ(PDF ビューアなど)を処理するサードパーティの拡張機能は、ネットワーク リクエストのインターセプトを利用してナビゲーションをキャッチし、ユーザーを拡張機能のページにリダイレクトしていました。MIME ハンドラとして登録すると、このアプローチのいくつかの制限を回避できます。
- 元の URL は、
chrome-extension://URL に置き換えられることなく、アドレスバーに残ります。 - 拡張機能は、2 回目のネットワーク リクエストを行うのではなく、Chrome がすでに受信したレスポンスを取得します。POST リクエストまたは使い捨て URL で配信されたドキュメントは正常に動作します。
- 拡張機能は、
<embed>、<object>、<iframe>要素内に読み込まれたドキュメントをレンダリングできます。 - ローカル ファイル(
file://URL)は、ユーザーが拡張機能の設定で [ファイル URL へのアクセスを許可する] を手動で有効にしなくても機能します。
MIME ハンドラは、フレーム全体を占有するドキュメント(最上位のナビゲーションと埋め込みドキュメント)にのみ適用されます。インライン サブリソース(<audio>、<img>、<video> 要素など)には適用されません。
ハンドラを登録する
拡張機能を MIME ハンドラとして登録するには、マニフェストで "mime_types_handler" キーを宣言します。各エントリは、MIME タイプをレンダリングする拡張機能ページにマッピングします。
manifest.json:
{
"name": "My PDF Viewer",
...
"mime_types_handler": {
"application/pdf": {
"handler_url": "viewer.html",
"can_embed": true
}
},
...
}
"can_embed" を true に設定して、<embed>、<object>、<iframe> 要素に埋め込まれたドキュメントも処理します。省略した場合、ハンドラは最上位のナビゲーションのみを受け取ります。Chrome 151 以降、application/pdf はパブリック ハンドラで使用できる唯一の MIME タイプです。サポートされていない MIME タイプを宣言すると、インストール警告が表示されます。
インストールされている複数の拡張機能が同じ MIME タイプを登録している場合、最後にインストールされた拡張機能が処理します。その拡張機能がアンインストールされると、以前にインストールされたハンドラが再びアクティブになります。
ストリーム情報を取得する
ユーザーが登録された MIME タイプのドキュメントを開くと、Chrome は組み込みのビューアの代わりにハンドラ ページを読み込みます。ハンドラ ページから getStreamInfo() を呼び出して、StreamInfo オブジェクトを取得します。これには、ユーザーが移動した originalUrl、HTTP responseHeaders、ドキュメントが embedded コンテキストで読み込まれたかどうか、ドキュメントのコンテンツの取得に使用できる streamUrl が含まれます。
streamUrl は 1 回だけ取得でき、拡張機能のオリジンからのみ取得できます。レスポンスを完全に読み取ってから処理します。同じ streamUrl の 2 回目のフェッチは失敗します。元のリクエストが繰り返せない可能性があるため、コンテンツを取得するのではなく、ドキュメントの場所やタイトルを表示する場合は originalUrl を使用します。
ネイティブ ハンドラにフォールバックする
ハンドラは、破損したファイルやパスワードで保護されたファイルなど、レンダリングできないドキュメントに遭遇する可能性があります。abortAndFallbackToNativeHandler() を呼び出して、ドキュメントの処理を停止し、破損したページにユーザーを残すのではなく、Chrome の組み込みビューアにドキュメントを返します。Chrome はフォールバックの一部としてハンドラページをアンロードします。この呼び出しの後にコードは実行されません。
Chrome は、ハンドラの実行中にレスポンスをバッファリングします。このメソッドを呼び出したときにレスポンスが完全に受信されている場合、Chrome は新しいネットワーク リクエストなしで、バッファリングされたコピーから組み込みビューアを提供します。そうでない場合、Chrome はネットワークからドキュメントを再読み込みしますが、POST で配信されたドキュメントや 1 回限りの URL からのドキュメントでは失敗する可能性があります。レンダリングできるかどうかを判断する前に、ストリームを完全に取得します。streamUrl の取得が完了すると、Chrome は完全なレスポンスを取得します。
API の可用性を処理する
Chrome 151 より前のバージョンの Chrome では、"mime_types_handler" を宣言する拡張機能は引き続きインストールされて実行されますが、ハンドラとして登録されず、browser.mimeHandler は未定義になります。ネットワーク リクエストのインターセプトから移行する拡張機能は、起動時に API を確認し、既存のアプローチをフォールバックとして維持できます。
service-worker.js:
if (browser.mimeHandler) {
// Chrome routes registered MIME types to the handler page
// declared in the manifest.
} else {
// Fall back to network request interception.
}
例
ストリームを処理する
次の例は、マニフェストで宣言されたハンドラ ページで実行されます。ドキュメントのコンテンツを取得し、レンダリングに失敗した場合は Chrome の組み込みビューアにフォールバックします。
viewer.js:
async function loadDocument() {
const streamInfo = await browser.mimeHandler.getStreamInfo();
// The `embedded` property is true if the document is loaded
// within an <embed>, <object>, or <iframe> element.
if (streamInfo.embedded) {
// Adjust the UI (e.g., hide the top navigation bar).
document.body.classList.add('embedded-view');
}
// Fetch the content using the provided streamUrl. The stream can
// only be consumed once, so read it fully before continuing.
const response = await fetch(streamInfo.streamUrl);
const data = await response.arrayBuffer();
try {
// Render the document (e.g., using PDF.js).
await renderDocument(data);
} catch (e) {
// Can't render this document. Fall back to Chrome's built-in
// viewer; the page unloads and no code runs after this call.
browser.mimeHandler.abortAndFallbackToNativeHandler();
}
}
loadDocument();
ユーザーが処理を切り替えられるようにする
ハンドラ オプションは MIME タイプごとに保存されます。次の例では、getMimeHandlerOptions() と setMimeHandlerOptions() を使用して、拡張機能をアンインストールせずに、オプション ページから処理をオフにできるようにしています。処理が無効になっている間、そのタイプのドキュメントは拡張機能に転送されなくなります。
options.js:
const checkbox = document.querySelector('#handle-pdfs');
async function initOptions() {
const options =
await browser.mimeHandler.getMimeHandlerOptions('application/pdf');
// Handling is enabled unless it has been explicitly disabled.
checkbox.checked = options.enabled !== false;
}
checkbox.addEventListener('change', async () => {
await browser.mimeHandler.setMimeHandlerOptions('application/pdf', {
enabled: checkbox.checked
});
});
initOptions();
型
MimeHandlerOptions
プロパティ
-
有効
ブール値
このハンドラが指定された MIME タイプに対してアクティブかどうか。
StreamInfo
プロパティ
-
埋め込み
ブール値
埋め込みコンテキスト(iframe/embed/object)で読み込まれた場合は true。
-
mimeType
文字列
インターセプトされたコンテンツの MIME タイプ。
-
originalUrl
文字列
ユーザーが移動した元の URL。
-
responseHeaders
オブジェクト
Key-Value ペアとしての HTTP レスポンス ヘッダー。
-
streamUrl
文字列
ストリームデータを取得する URL。
-
tabId
数値
ドキュメントを含むタブの ID。
メソッド
abortAndFallbackToNativeHandler()
chrome.mimeHandler.abortAndFallbackToNativeHandler(): Promise<void>
現在のストリーム処理を中止し、コンテンツをユーザー エージェントのネイティブ ハンドラに渡します。この呼び出しの後、拡張機能フレームは破棄されます。呼び出し元は、それ以上の実行を想定しないでください。
戻り値
-
Promise<void>
getMimeHandlerOptions()
chrome.mimeHandler.getMimeHandlerOptions(
mimeType: string,
): Promise<MimeHandlerOptions>
MIME タイプの永続化されたオプションを読み取ります。保存されていない場合は、デフォルト値(enabled=true)を返します。
パラメータ
-
mimeType
文字列
オプションを読み取る MIME タイプ。
戻り値
-
Promise<MimeHandlerOptions>
MIME タイプの永続化されたオプションで解決された Promise。
getStreamInfo()
chrome.mimeHandler.getStreamInfo(): Promise<StreamInfo>
現在の MIME ハンドラのコンテキストのストリーム情報を取得します。MIME ハンドラ拡張機能のページ内から呼び出す必要があります。
戻り値
-
Promise<StreamInfo>
setMimeHandlerOptions()
chrome.mimeHandler.setMimeHandlerOptions(
mimeType: string,
options: MimeHandlerOptions,
): Promise<void>
指定された MIME タイプの構成オプションを設定します。
パラメータ
-
mimeType
文字列
構成する MIME タイプ。
-
オプション
使用する新しいオプション。
戻り値
-
Promise<void>
構成が設定されると Promise が解決されます。