説明
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 の時点では、パブリック ハンドラで使用できる MIME タイプは application/pdf のみです。サポートされていない MIME タイプを宣言すると、インストールに関する警告が表示されます。
インストールされている複数の拡張機能が同じ MIME タイプに登録されている場合、最後にインストールされた拡張機能が処理します。その拡張機能がアンインストールされると、以前にインストールされたハンドラが再び有効になります。
ストリーム情報を取得する
ユーザーが登録された MIME タイプのドキュメントを開くと、Chrome は組み込みビューアの代わりにハンドラページを読み込みます。ハンドラページから getStreamInfo() を呼び出して、StreamInfo オブジェクトを取得します。これには、ユーザーが移動した originalUrl、HTTP responseHeaders、ドキュメントが embedded コンテキストに読み込まれているかどうか、ドキュメントのコンテンツの取得に使用できる streamUrl が含まれます。
streamUrl は 1 回だけ取得でき、拡張機能のオリジンからのみ取得できます。レスポンスを処理する前に完全に読み取ります。同じ streamUrl を 2 回取得すると失敗します。ドキュメントの場所やタイトルを表示する場合は、originalUrl を使用します。元のリクエストは繰り返せない可能性があるため、コンテンツの取得には使用しないでください。
ネイティブ ハンドラにフォールバックする
ハンドラは、破損したファイルやパスワードで保護されたファイルなど、レンダリングできないドキュメントに遭遇する可能性があります。abortAndFallbackToNativeHandler() を呼び出して、ドキュメントの処理を停止し、破損したページにユーザーを残すのではなく、Chrome の組み込みビューアに返します。Chrome はフォールバックの一部としてハンドラページをアンロードします。この呼び出しの後、コードは実行されません。
ハンドラの実行中、Chrome はレスポンスをバッファに格納します。このメソッドを呼び出したときにレスポンスが完全に受信されている場合、Chrome は新しいネットワーク リクエストを行わずに、バッファに格納されたコピーから組み込みビューアを提供します。それ以外の場合、Chrome はネットワークからドキュメントを再読み込みします。これは、POST または使い捨て URL で配信されるドキュメントでは失敗する可能性があります。ストリームをレンダリングできるかどうかを判断する前に、ストリームを完全に取得します。streamUrl の取得が完了すると、Chrome は完全なレスポンスを取得します。
API の可用性を処理する
Chrome 151 より前のバージョンの Chrome では、"mime_types_handler" を宣言する拡張機能はインストールされて実行されますが、ハンドラとして登録されず、chrome.mimeHandler は未定義になります。ネットワーク リクエストのインターセプトから移行する拡張機能は、起動時に API を確認し、フォールバックとして既存の方法を維持できます。
service-worker.js:
if (chrome.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 chrome.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.
chrome.mimeHandler.abortAndFallbackToNativeHandler();
}
}
loadDocument();
ユーザーが処理を切り替えられるようにする
ハンドラ オプションは MIME タイプごとに保存されます。次の例では、getMimeHandlerOptions() と setMimeHandlerOptions() を使用して、拡張機能をアンインストールせずに、オプション ページからユーザーが処理をオフにできるようにします。処理が無効になっている間、そのタイプのドキュメントは拡張機能にルーティングされなくなります。
options.js:
const checkbox = document.querySelector('#handle-pdfs');
async function initOptions() {
const options =
await chrome.mimeHandler.getMimeHandlerOptions('application/pdf');
// Handling is enabled unless it has been explicitly disabled.
checkbox.checked = options.enabled !== false;
}
checkbox.addEventListener('change', async () => {
await chrome.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。