説明
chrome.mimeHandler API を使用して、サードパーティの拡張機能で MIME タイプ ストリームを処理します。
対象
マニフェスト
コンセプトと使用方法
これまで、特定のドキュメント タイプを処理するサードパーティの拡張機能(PDF ビューアなど)は、ネットワーク リクエストのインターセプトに依存してナビゲーションをキャッチし、ユーザーを拡張機能ページにリダイレクトしていました。MIME ハンドラとして登録すると、このアプローチのいくつかの制限を回避できます。
- 元の URL は
chrome-extension://URL に置き換えられず、アドレスバーに表示されたままになります。 - 拡張機能は、2 回目のネットワーク リクエストを行う代わりに、Chrome がすでに受信したレスポンスを取得します。POST リクエストまたは 1 回限りの 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 以降、パブリック ハンドラで使用できる MIME タイプは 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
プロパティ
-
canEmbed
boolean 省略可
Chrome 157 以降このハンドラを埋め込み読み込み(iframe、embed、object)に使用できるかどうか。デフォルトは、マニフェスト エントリの
can_embed値です。enabledが false の場合は無効です。 -
有効
boolean 省略可
このハンドラが有効かどうか。デフォルトは、マニフェスト エントリの
enabled値です。
StreamInfo
プロパティ
-
組み込み型
ブール値
埋め込みコンテキスト(iframe / 埋め込み / オブジェクト)で読み込まれた場合は 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 タイプのオプションを読み取ります。各メンバーは、拡張機能が設定した値です。拡張機能が設定していない場合は、マニフェスト エントリの値です。
パラメータ
-
mimeType
文字列
オプションを読み取る MIME タイプ。拡張機能が mime_types_handler を介して処理する 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 タイプ。拡張機能が mime_types_handler を介して処理する MIME タイプである必要があります。
-
オプション
変更するオプション。
戻り値
-
Promise<void>
構成が設定されると、Promise が解決されます。