mcpField
B
browserenginekit

browserenginekit

github.com/dpearson2699開発1.2k3.1k 回インストール13 週間前に更新
リポジトリ

browserenginekit について

BrowserEngineKit は、iOS と iPadOS 向けに代替ブラウザーエンジンを構築する開発者向けのスキルです。プロセス分離、拡張間通信、ケイパビリティ管理、システム連携に加え、利用資格や権限、安全要件を解説します。

主な機能

  1. 01Web コンテンツ・ネットワーク・描画拡張の分離
  2. 02XPC による分離プロセス間の連携
  3. 03拡張への実行ケイパビリティ付与
  4. 04レイヤー階層の表示と更新同期
  5. 05テキスト操作とダウンロード監視の統合
  6. 06サンドボックスとエンジン権限の設定

活用シーン

  1. 01独自 HTML エンジンを使うブラウザーの構築
  2. 02Web コンテンツとネットワーク処理の分離
  3. 03プロセス間の描画とメディア機能の管理
  4. 04代替エンジンの利用資格と安全設定の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dpearson2699/swift-ios-skills --skill browserenginekit

インストール後、Claude Code で/browserenginekitを入力して読み込まれたか確認します。

同梱ファイルevals/evals.jsonreferences/browserenginekit-patterns.md

詳細

BrowserEngineKit

iOS および iPadOS で、代替の(WebKit 以外の)レンダリングエンジンを使用する Web ブラウザーを構築するためのフレームワークです。独自の HTML/CSS/JavaScript エンジンを実装するブラウザーアプリ向けに、プロセス分離、XPC 通信、ケイパビリティ管理、システム統合を提供します。サンプルは Swift 6.3 と最新の Apple SDK を対象としています。

BrowserEngineKit は特殊なフレームワークです。代替ブラウザーエンジンを利用できるのは、Apple が承認したエンタイトルメントプロファイルを利用し、対象地域で使用可能なデバイスに限られます。EU では iOS 17.4 以降および iPadOS 18 以降の対象ユーザーが利用できます。日本では iOS 26.2 からサポートが始まり、ブラウザーアプリに PAC/MIE の明示的なセキュリティ要件が追加されます。開発とテストはどこでも実施できます。関連するフレームワークである BrowserEngineCore(低レベルのプリミティブ)と BrowserKit(利用資格の確認、データ転送)は、ワークフロー全体をサポートします。

目次

概要と利用資格

利用資格の確認

BrowserKit フレームワークの BEAvailability を使用して、デバイスが代替ブラウザーエンジンの利用対象かどうかを確認します。BEAvailability は iOS/iPadOS 18.4 以降で利用できます。

import BrowserKit

do {
    let eligible = try await BEAvailability.isEligible(for: .webBrowser)
    guard eligible else { return /* fall back or explain */ }
    // Device supports alternative browser engines
} catch {
    // Handle eligibility lookup failure
}

利用資格はデバイスの地域と OS バージョンによって異なります。地域をハードコードせず、システム API を使用してください。

利用可能な OS バージョンの目安:プロセス API は iOS/iPadOS 17.4 以降、BEDownloadMonitor は iOS 18.2 以降、制限付きサンドボックスの .revision2 は iOS 26 以降、RenderingExtensionFeature.coreML は iOS 26.2 以降です。

エンタイトルメント

ブラウザーアプリ(ホスト)

ホストアプリには 2 つのエンタイトルメントが必要です。

エンタイトルメント目的
com.apple.developer.web-browserデフォルトブラウザー候補になる機能を有効にします
com.apple.developer.web-browser-engine.host代替エンジン拡張機能を有効にします

どちらも Apple に申請する必要があります。申請手続きは地域によって異なります。

拡張機能のエンタイトルメント

各拡張機能ターゲットでは、その種類に応じたエンタイトルメントを true に設定する必要があります。

拡張機能の種類エンタイトルメント
Web コンテンツcom.apple.developer.web-browser-engine.webcontent
ネットワークcom.apple.developer.web-browser-engine.networking
レンダリングcom.apple.developer.web-browser-engine.rendering
オプションのエンタイトルメント
エンタイトルメント拡張機能目的
com.apple.security.cs.allow-jitWeb コンテンツスクリプトの JIT コンパイル
com.apple.developer.kernel.extended-virtual-addressingWeb コンテンツJIT と併せて必須
com.apple.developer.memory.transfer_sendレンダリングメモリの帰属情報を送信します。値はホストアプリのバンドル ID です
com.apple.developer.memory.transfer_acceptWeb コンテンツメモリの帰属情報を受け入れます。値はホストアプリのバンドル ID です
com.apple.developer.web-browser-engine.restrict.notifydWeb コンテンツ通知デーモンへのアクセスを制限します
埋め込みブラウザーエンジン(ブラウザー以外のアプリ)

ブラウザーではなく、アプリ内ブラウジング用に代替エンジンを埋め込むアプリでは、異なるエンタイトルメントを使用します。

エンタイトルメント目的
com.apple.developer.embedded-web-browser-engine埋め込みエンジンを有効にします
com.apple.developer.embedded-web-browser-engine.engine-associationエンジンの所有者を宣言します

engine-association は iOS/iPadOS/Mac Catalyst 26.2 以降で利用でき、自社がエンジンを所有している場合は first-party、別の開発者が所有している場合は third-party に設定します。埋め込みエンジンは arm64 のみ(arm64e は不可)を使用し、ブラウザー拡張機能を含めることはできず、JIT コンパイルも使用できません。

日本固有の要件

日本で配布されるブラウザーアプリは iOS 26.2+ でサポートされており、Pointer Authentication Codes や、該当するアロケーターおよび拡張プロセスに対する Memory Integrity Enforcement など、Apple が日本向けに指定している最新のセキュリティ緩和策を採用する必要があります。 com.apple.security.hardened-process.checked-allocations を使用してハードウェアメモリータグ付けを有効にしてください。Apple は EU でも有効にすることを強く推奨しています。

アーキテクチャ

BrowserEngineKit で構築されたブラウザーは、別々のプロセスで実行される 4 つのコンポーネントで構成されます。

Host App (UI, coordination)
  |
  |-- XPC --> Web Content Extension (HTML parsing, JS, DOM)
  |-- XPC --> Networking Extension (URLSession, sockets)
  |-- XPC --> Rendering Extension (Metal, GPU, media)

ホストアプリはすべての拡張機能を起動し、管理します。拡張機能が別の拡張機能を起動することはできません。拡張機能同士は、ホストアプリが仲介する匿名 XPC エンドポイントを介して通信します。

ブートストラップシーケンス
  1. ホストがウェブコンテンツ、ネットワーキング、レンダリングの各拡張機能を起動します
  2. ホストが各拡張機能への XPC 接続を作成します
  3. ホストがネットワーキング拡張機能とレンダリング拡張機能から匿名 XPC エンドポイントを要求します
  4. ホストがブートストラップメッセージを介して両方のエンドポイントをウェブコンテンツ拡張機能に送信します
  5. ウェブコンテンツ拡張機能がネットワーキングおよびレンダリング拡張機能に直接接続します

このアーキテクチャは最小権限の原則に従っています。ウェブコンテンツ拡張機能は信頼できないデータを扱いますが、OS リソースには直接アクセスできません。

プロセス管理

拡張機能の起動

ホストアプリには、各拡張機能タイプに対応するプロセスクラスがあります。

import BrowserEngineKit

// Web content (one per tab or iframe)
let contentProcess = try await WebContentProcess(
    bundleIdentifier: nil,
    onInterruption: {
        // Handle crash or OS interruption
    }
)

// Networking (typically one instance)
let networkProcess = try await NetworkingProcess(
    bundleIdentifier: nil,
    onInterruption: {
        // Handle interruption
    }
)

// Rendering / GPU (typically one instance)
let renderingProcess = try await RenderingProcess(
    bundleIdentifier: nil,
    onInterruption: {
        // Handle interruption
    }
)

デフォルトの拡張機能ターゲットを使用するには、bundleIdentifier に nil を渡します。拡張機能がクラッシュした場合、または OS によって終了された場合に、割り込みハンドラーが呼び出されます。

XPC 接続の作成
let connection = try contentProcess.makeLibXPCConnection()
// Use connection for inter-process messaging

各プロセスタイプには、通信に使用する xpc_connection_t を作成する makeLibXPCConnection() が用意されています。

拡張機能の停止
contentProcess.invalidate()

invalidate() の呼び出し後は、プロセスオブジェクトに対するメソッド呼び出しは無効です。

拡張機能の種類

ウェブコンテンツ拡張機能

ブラウザーエンジンの HTML パーサー、CSS エンジン、JavaScript インタープリター、DOM をホストします。受信する XPC 接続を処理するには、WebContentExtension に準拠させます。

import BrowserEngineKit

@main
struct MyWebContentExtension: WebContentExtension {
    func handle(xpcConnection: xpc_connection_t) {
        // Set up message handlers on the connection
    }
}

拡張機能の EXAppExtensionAttributes で WebContentExtensionConfiguration を使用して設定します。

ネットワーキング拡張機能

URLSession またはソケット API を使用して、すべてのネットワークリクエストを処理します。1 つのインスタンスですべてのタブに対応します。

import BrowserEngineKit

@main
struct MyNetworkingExtension: NetworkingExtension {
    func handle(xpcConnection: xpc_connection_t) {
        // Handle network request messages
    }
}

NetworkingExtensionConfiguration を使用して設定します。

レンダリング拡張機能

Metal を介して GPU にアクセスし、ビデオデコード、合成、複雑なレンダリングを行います。通常、1 つのインスタンスでブラウザー全体に対応します。

import BrowserEngineKit

@main
struct MyRenderingExtension: RenderingExtension {
    init() {
        if #available(iOS 26.2, macOS 26.2, *) {
            enableFeature(.coreML)
        }
    }

    func handle(xpcConnection: xpc_connection_t) {
        // Handle rendering commands
    }
}

RenderingExtensionConfiguration を使用して設定します。

ケイパビリティ

拡張機能にケイパビリティを付与し、OS が適切にスケジュールできるようにします。

// Grant foreground priority to an extension
let grant = try contentProcess.grantCapability(.foreground)

// ... extension does foreground work ...

// Relinquish when done
grant.invalidate()
利用可能なケイパビリティ
ケイパビリティ用途
.foregroundアクティブなタブのレンダリング、表示中のコンテンツ
.backgroundバックグラウンドタスク、先読み
.suspended最小限のアクティビティ、保留中のクリーンアップ
.mediaPlaybackAndCapture(environment:)オーディオ/ビデオ再生、カメラ/マイクのキャプチャ
メディア環境

メディアケイパビリティには、ページ URL に関連付けられた MediaEnvironment を作成します。 この環境はカメラ/マイクへのアクセスに AVCaptureSession をサポートし、プロセス間転送のために XPC でシリアライズできます。

let mediaEnv = MediaEnvironment(webPage: pageURL)
let grant = try contentProcess.grantCapability(
    .mediaPlaybackAndCapture(environment: mediaEnv)
)
try mediaEnv.activate()
let captureSession = try mediaEnv.makeCaptureSession()
可視性の伝播

ブラウザービューに可視性伝播インタラクションをアタッチすると、コンテンツが画面上に表示されていることを拡張機能に知らせられます。WebContentProcess と RenderingProcess の両方が createVisibilityPropagationInteraction() を提供します。

レイヤーホスティングとビューの調整

レンダリング拡張機能は LayerHierarchy に描画し、ホストアプリはそのコンテンツを LayerHierarchyHostingView を介して表示します。ハンドルは XPC 経由で渡されます。LayerHierarchyHostingTransactionCoordinator を使用して、プロセス間のレイヤー更新をアトミックに同期します。

レイヤーホスティングの詳細な例とトランザクションの調整については、references/browserenginekit-patterns.md を参照してください。

テキスト操作

カスタムテキストビューで BETextInput を採用し、UIKit のテキストシステムと統合します。これにより、標準のテキスト選択、自動修正、音声入力、キーボード操作が利用できます。

主な統合ポイント:

  • テキストの変更をシステムに伝える asyncInputDelegate
  • キーボードイベントを処理する handleKeyEntry(_:completionHandler:)
  • 選択ジェスチャ、編集メニュー、コンテキストメニューのための BETextInteraction
  • カスタムスクロール処理のための BEScrollView と BEScrollViewDelegate

テキスト操作の実装について詳しくは、references/browserenginekit-patterns.md を参照してください。

サンドボックスとセキュリティ

制限付きサンドボックス

初期化後、制限付きサンドボックスを使用してコンテンツ拡張機能を制限します。

// In the web content extension, after setup:
if #available(iOS 26.0, macOS 26.0, *) {
    applyRestrictedSandbox(revision: .revision2)
} else {
    applyRestrictedSandbox(revision: .revision1)
}

これにより、拡張機能が起動時に使用していたものの、その後不要になったリソースへのアクセスが削除されます。最も強い制限を適用するには、利用可能な最新のリビジョンを使用してください。

JIT コンパイル

JavaScript を JIT コンパイルする Web コンテンツ拡張機能では、BrowserEngineKit の証明付き API を使ってページを切り替える必要があります。

import BrowserEngineCore

be_memory_inline_jit_restrict_rwx_to_rw_with_witness(...)
// write generated code
be_memory_inline_jit_restrict_rwx_to_rx_with_witness(...)

Web コンテンツ拡張機能のみに com.apple.security.cs.allow-jit と com.apple.developer.kernel.extended-virtual-addressing のエンタイトルメントが必要です。実装で代わりに pthread_jit_write_with_callback_np を使用する場合は、JIT 書き込み許可リストのエンタイトルメントも必要です。BE_JIT_WRITE_PROTECT_TAG だけで完全な保護対策になるとは示さないでください。

arm64e の要件

配布用ビルドは、現在の代替ブラウザ向けエンタイトルメントプロファイルで定められたデバイスアーキテクチャ、PAC、MIE の要件を満たす必要があります。ホストと拡張機能の構成に一貫性を持たせ、必要なデバイススライスを含め、対象デバイスで署名済みアーカイブをテストしてください。組み込みエンジンは要件が異なり、arm64 のみで、JIT は使用できません。Simulator ビルドに arm64e を強制したり、必要なスライスを削除する一行の ARCHS 上書きをコピーしたりしないでください。

ダウンロード

BEDownloadMonitor を使用して、ダウンロードの進行状況をシステムに報告します。アクセストークンを作成し、ソース/宛先 URL と Progress オブジェクトを指定してモニターを初期化したら、beginMonitoring() を呼び出してシステムのダウンロード UI を表示します。中断されたダウンロードを再開するには resumeMonitoring(placeholderURL:) を使用します。BEDownloadMonitor は iOS 18.2 以降で利用できます。

ダウンロード管理の詳しい例については、references/browserenginekit-patterns.md を参照してください。

よくある間違い

やってはいけないこと:ブートストラップの手順を省略する
// WRONG - content extension has no path to other extensions
let contentProcess = try await WebContentProcess(
    bundleIdentifier: nil, onInterruption: {}
)
// Immediately start sending work without connecting to networking/rendering

// CORRECT - broker connections through the host app
let networkEndpoint = try await networkProxy.getEndpoint()
let renderEndpoint = try await renderProxy.getEndpoint()
try await contentProxy.bootstrap(
    renderingExtension: renderEndpoint,
    networkExtension: networkEndpoint
)
やってはいけないこと:別の拡張機能から拡張機能を起動する
// WRONG - extensions cannot launch other extensions
// (inside a WebContentExtension)
let network = try await NetworkingProcess(...)

// CORRECT - only the host app launches extensions
// Host app creates all processes, then brokers connections
やってはいけないこと:無効化後に拡張機能プロセスのオブジェクトを使用する
// WRONG
contentProcess.invalidate()
let conn = try contentProcess.makeLibXPCConnection()  // Error

// CORRECT - create a new process if needed
let newProcess = try await WebContentProcess(
    bundleIdentifier: nil, onInterruption: {}
)
やってはいけないこと:コンテンツ拡張機能以外に JIT エンタイトルメントを適用する

JIT コンパイルのエンタイトルメント(com.apple.security.cs.allow-jit)は、Web コンテンツ拡張機能でのみ有効です。ホストアプリ、レンダリング拡張機能、またはネットワーク拡張機能に追加すると、App Store で却下されます。

やってはいけないこと:対象地域の適格性をハードコードする
// WRONG
if Locale.current.region?.identifier == "DE" {
    useAlternativeEngine()
}

// CORRECT - use the system eligibility API
let eligible = try await BEAvailability.isEligible(for: .webBrowser)
if eligible {
    useAlternativeEngine()
}
やってはいけないこと:UIRequiredDeviceCapabilities の設定を忘れる

UIRequiredDeviceCapabilities に web-browser-engine がないと、サポートされていないデバイスのユーザーがアプリをダウンロードし、実行時に失敗する可能性があります。

レビューチェックリスト

  • ホストアプリに com.apple.developer.web-browser-engine.host エンタイトルメントが設定されている
  • 各拡張機能に、種類固有のエンタイトルメントが設定されている
  • UIRequiredDeviceCapabilities に web-browser-engine が含まれている
  • すべての iOS デバイス向けターゲットで arm64e 命令セットが設定されている
  • シミュレーター向けターゲットでは arm64e が設定されていない
  • Swift パッケージが、ワークスペース設定 iOSPackagesShouldBuildARM64e を使用してビルドされている
  • 各拡張機能の Info.plist で、拡張ポイント識別子が正しく設定されている
  • すべてのプロセスタイプに割り込みハンドラーが実装されている
  • ブートストラップシーケンスによって、コンテンツ拡張機能がネットワーク処理とレンダリングに接続されている
  • 作業開始前にケイパビリティが付与され、完了時に無効化されている
  • ブラウザーのコンテンツビューに可視性伝播の処理が追加されている
  • 初期化後、コンテンツ拡張機能に制限付きサンドボックスが適用されている
  • 対象地域の確認に手動の地域判定ロジックではなく BEAvailability が使用されている
  • メモリ帰属エンタイトルメントの値として、ホストアプリのバンドル ID が使用されている
  • iOS 18.2 以降では、進行中のダウンロードの進捗が BEDownloadMonitor を介して報告されている
  • iOS 26.2 以降では、日本での配布に向けてメモリタグ付けが有効になっている(EU でも推奨)

参考資料

コメント