# 機能設計書 42-Webビュー

## 概要

本ドキュメントは、VS CodeのWebビュー機能に関する機能設計書である。カスタムWebコンテンツをエディタ内で表示・操作するための基盤機能を定義する。

### 本機能の処理概要

WebビューはHTML/CSS/JavaScriptで構成されたカスタムコンテンツをVS Code内に表示するための機能である。拡張機能がリッチなUIを提供するための基盤となる。

**業務上の目的・背景**：VS Codeの標準UIでは表現しきれないリッチなコンテンツ（ドキュメントプレビュー、カスタムエディタ、ダッシュボード等）を拡張機能が提供できるようにする。これによりVS Codeの拡張性を大幅に向上させ、様々な開発ワークフローに対応可能にする。

**機能の利用シーン**：
- Markdownプレビューの表示
- カスタムエディタ（SVG、画像編集等）の実装
- 拡張機能のウェルカムページ・設定画面
- ノートブックの出力セルレンダリング
- チャット機能のリッチ出力表示

**主要な処理内容**：
1. Webviewインスタンスの生成（iframe要素の作成）
2. HTMLコンテンツの設定とレンダリング
3. VS Codeとの双方向メッセージング
4. ローカルリソースの読み込み（Service Worker経由）
5. セキュリティ制御（CSP、オリジン分離）
6. テーマ連携とスタイル適用
7. 検索ウィジェットの提供

**関連システム・外部連携**：
- 拡張機能ホスト（Extension Host）からのWebview API呼び出し
- ファイルシステムサービス（ローカルリソースの読み込み）
- テーマサービス（CSS変数の提供）
- トンネルサービス（ポートマッピング）
- ストレージサービス（オリジンの永続化）

**権限による制御**：
- `localResourceRoots`によるローカルファイルアクセス制限
- `enableCommandUris`によるコマンド実行制御
- `allowScripts`によるスクリプト実行制御
- CSP（Content Security Policy）による外部リソースアクセス制御

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | エディタペイン | 主画面 | カスタムエディタとしてのWebview表示 |
| - | サイドバーパネル | 参照画面 | Webview Viewとしての表示 |

## 機能種別

UI描画 / メッセージング / リソース管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| providedViewType | string | No | Webviewのビュータイプ識別子 | - |
| origin | string | No | オリジン識別子（指定なしでUUID生成） | - |
| title | string | No | Webviewのタイトル | - |
| options | WebviewOptions | Yes | 表示オプション | - |
| contentOptions | WebviewContentOptions | Yes | コンテンツオプション | - |
| extension | WebviewExtensionDescription | No | 所有拡張機能の情報 | - |

### WebviewOptions詳細

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|-----|------|
| purpose | WebviewContentPurpose | No | 用途（notebookRenderer/customEditor/webviewView/chatOutputItem） |
| customClasses | string | No | カスタムCSSクラス |
| enableFindWidget | boolean | No | 検索ウィジェット有効化 |
| disableServiceWorker | boolean | No | Service Worker無効化 |
| tryRestoreScrollPosition | boolean | No | スクロール位置復元 |
| retainContextWhenHidden | boolean | No | 非表示時のコンテキスト維持 |

### WebviewContentOptions詳細

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|-----|------|
| allowMultipleAPIAcquire | boolean | No | acquireVsCodeApiの複数回呼び出し許可 |
| allowScripts | boolean | No | スクリプト実行許可（デフォルトfalse） |
| allowForms | boolean | No | フォーム許可（デフォルトはallowScripts値） |
| localResourceRoots | URI[] | No | ローカルリソースアクセス許可パス |
| portMapping | IWebviewPortMapping[] | No | ポートマッピング設定 |
| enableCommandUris | boolean \| string[] | No | コマンドURI許可 |

### 入力データソース

- 拡張機能からのWebview API呼び出し
- HTMLコンテンツ文字列
- ローカルファイルシステム（リソース読み込み）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| IWebview | interface | Webviewインスタンス |
| IWebviewElement | interface | DOM要素としてのWebview |
| IOverlayWebview | interface | オーバーレイ配置のWebview |

### 出力先

- エディタ領域（iframeとして描画）
- サイドバー・パネル領域（WebviewView）
- メッセージイベント（拡張機能への通知）

## 処理フロー

### 処理シーケンス

```
1. Webview生成リクエスト
   └─ createWebviewElement() または createWebviewOverlay() を呼び出し

2. iframe要素の作成
   └─ _createElement() で iframe を生成
   └─ sandbox属性、CSP設定を適用

3. Service Workerの初期化
   └─ リソース読み込み用Service Workerを登録
   └─ バージョンチェックと更新

4. HTMLコンテンツの設定
   └─ setHtml() でコンテンツを注入
   └─ テーマ変数のCSS注入

5. メッセージチャネルの確立
   └─ MessagePort を介した双方向通信
   └─ VS Code API の提供

6. イベント監視
   └─ フォーカス、スクロール、クリック等のイベントを監視
   └─ 拡張機能へイベントを転送
```

### フローチャート

```mermaid
flowchart TD
    A[Webview生成要求] --> B{Webviewタイプ?}
    B -->|Element| C[WebviewElement作成]
    B -->|Overlay| D[OverlayWebview作成]
    C --> E[iframe生成]
    D --> E
    E --> F[Service Worker初期化]
    F --> G[HTMLコンテンツ設定]
    G --> H[MessagePort確立]
    H --> I[イベント監視開始]
    I --> J[Webview使用可能]
    J --> K{ユーザー操作}
    K -->|メッセージ送信| L[postMessage]
    K -->|フォーカス| M[onDidFocus発火]
    K -->|リンククリック| N[onDidClickLink発火]
    L --> O[拡張機能へ転送]
    M --> O
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-42-01 | オリジン分離 | 各Webviewは一意のオリジンを持ち、他のWebviewからのアクセスを防止 | 全Webview |
| BR-42-02 | リソースアクセス制限 | localResourceRoots内のファイルのみアクセス可能 | ローカルリソース読み込み時 |
| BR-42-03 | スクリプト制御 | allowScripts=falseの場合、スクリプト実行を完全にブロック | HTMLコンテンツ設定時 |
| BR-42-04 | コンテンツオプション比較 | areWebviewContentOptionsEqual()で変更検出 | オプション更新時 |

### 計算ロジック

**オリジン生成**：
```typescript
// WebviewOriginStore.getOrigin() より
public getOrigin(viewType: string, additionalKey: string | undefined): string {
    const existing = this._state[key];
    if (existing) return existing;
    const newOrigin = generateUuid();
    this._state[key] = newOrigin;
    return newOrigin;
}
```

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| オリジン永続化 | IStorageService | INSERT/SELECT | Webviewオリジンの保存・取得 |
| 状態保存 | IStorageService | UPDATE | Webviewの状態永続化 |

### テーブル別操作詳細

#### StorageService（アプリケーションスコープ）

| 操作 | 項目（キー） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/SELECT | webview.origins | JSON形式のオリジンマップ | viewType+extensionIdでキー化 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| CSP_MISSING | セキュリティエラー | CSPが設定されていないWebview | onMissingCspイベント発火、警告通知 |
| FATAL_ERROR | システムエラー | Webviewがクラッシュ | onFatalErrorイベント発火、再読み込み提案 |
| RESOURCE_NOT_FOUND | 業務エラー | ローカルリソースが見つからない | 404レスポンスを返す |
| RESOURCE_ACCESS_DENIED | セキュリティエラー | localResourceRoots外へのアクセス | 403レスポンスを返す |

### リトライ仕様

Webviewのクラッシュ時は`reload()`メソッドで再読み込み可能。自動リトライは行わない。

## トランザクション仕様

Webviewの操作はトランザクション制御を行わない。状態変更は即座に反映される。

## パフォーマンス要件

- iframeの遅延作成（OverlayWebviewでのclaim/releaseパターン）
- Service Workerによるリソースキャッシュ
- フォーカスイベントの50msスロットリング
- 非表示時のコンテキスト破棄オプション（retainContextWhenHidden）

## セキュリティ考慮事項

- **オリジン分離**：各WebviewにユニークなオリジンUUIDを割り当て
- **CSP強制**：Content Security Policyによる外部リソース制限
- **sandbox属性**：iframeのsandbox属性でブラウザ機能を制限
- **リソースアクセス制御**：localResourceRootsによるファイルアクセス制限
- **コマンドURI制御**：enableCommandUrisによるコマンド実行制限

## 備考

- Webviewは拡張機能API（vscode.webview）を通じて利用される
- Electron環境とWeb環境で実装が異なる（webviewElement.ts vs electron-browser/webviewElement.ts）

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

Webviewで使用される主要なインターフェースと型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | webview.ts | `src/vs/workbench/contrib/webview/browser/webview.ts` | IWebviewService（38-70行目）、IWebview（181-274行目）、WebviewOptions（93-109行目）、WebviewContentOptions（111-143行目）を確認 |
| 1-2 | webview.ts (common) | `src/vs/workbench/contrib/webview/common/webview.ts` | webviewRootResourceAuthority、デコード/エンコード関数 |

**読解のコツ**: IWebviewServiceがファクトリ、IWebviewが生成されるインスタンスのインターフェース。IWebviewElement（DOM直接配置）とIOverlayWebview（オーバーレイ配置）の2種類がある。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | webviewService.ts | `src/vs/workbench/contrib/webview/browser/webviewService.ts` | WebviewService クラス（14-80行目）がWebview生成のエントリーポイント |

**主要処理フロー**:
1. **46-50行目**: `createWebviewElement()` でWebviewElement生成
2. **52-56行目**: `createWebviewOverlay()` でOverlayWebview生成
3. **58-79行目**: `registerNewWebview()` でフォーカス・破棄イベントの監視登録

#### Step 3: Webview要素の実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | webviewElement.ts | `src/vs/workbench/contrib/webview/browser/webviewElement.ts` | WebviewElement クラスがiframe生成の実体 |

**主要処理フロー**:
- **77行目**: `WebviewElement extends Disposable implements IWebviewElement`
- **153-200行目**: コンストラクタで初期化、iframe作成、イベントハンドラ登録
- **188行目**: `_createElement()` でiframe要素生成
- **198-199行目**: メッセージハンドラの登録

#### Step 4: オーバーレイWebviewを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | overlayWebview.ts | `src/vs/workbench/contrib/webview/browser/overlayWebview.ts` | OverlayWebview クラスの遅延生成パターン |

**主要処理フロー**:
- `claim()` でWebview所有権を取得し、基底のWebviewElementを生成
- `release()` で所有権を解放し、Webviewを破棄
- `layoutWebviewOverElement()` で位置決め

#### Step 5: リソース読み込みを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | resourceLoading.ts | `src/vs/workbench/contrib/webview/browser/resourceLoading.ts` | ローカルリソースの読み込み処理 |

**主要処理フロー**:
- `loadLocalResource()` 関数でファイルシステムからリソース取得
- localResourceRootsによるアクセス制御
- MIME タイプの判定

### プログラム呼び出し階層図

```
WebviewService (webviewService.ts)
    │
    ├─ createWebviewElement()
    │      └─ WebviewElement (webviewElement.ts)
    │             ├─ _createElement() [iframe生成]
    │             ├─ Service Worker [リソース読み込み]
    │             └─ MessagePort [メッセージング]
    │
    └─ createWebviewOverlay()
           └─ OverlayWebview (overlayWebview.ts)
                  ├─ claim() [遅延生成]
                  ├─ release() [破棄]
                  └─ layoutWebviewOverElement() [配置]
```

### データフロー図

```
[入力]                    [処理]                         [出力]

HTML文字列         ───▶ setHtml()               ───▶ iframe描画
(拡張機能から)              │
                           ▼
                    テーマCSS注入
                           │
                           ▼
postMessage()      ───▶ MessagePort          ───▶ onMessage Event
(VS Code → Webview)        │                        (Webview → 拡張機能)
                           │
ローカルリソース   ◀─── Service Worker        ◀─── vscode-resource:// URL
リクエスト                  │                        (Webview内から)
                           ▼
                    loadLocalResource()       ───▶ ファイル内容
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| webview.ts | `src/vs/workbench/contrib/webview/browser/webview.ts` | ソース | インターフェース定義 |
| webviewService.ts | `src/vs/workbench/contrib/webview/browser/webviewService.ts` | ソース | サービス実装 |
| webviewElement.ts | `src/vs/workbench/contrib/webview/browser/webviewElement.ts` | ソース | Webview要素実装 |
| overlayWebview.ts | `src/vs/workbench/contrib/webview/browser/overlayWebview.ts` | ソース | オーバーレイWebview |
| resourceLoading.ts | `src/vs/workbench/contrib/webview/browser/resourceLoading.ts` | ソース | リソース読み込み |
| themeing.ts | `src/vs/workbench/contrib/webview/browser/themeing.ts` | ソース | テーマ連携 |
| webviewFindWidget.ts | `src/vs/workbench/contrib/webview/browser/webviewFindWidget.ts` | ソース | 検索ウィジェット |
| webviewPortMapping.ts | `src/vs/platform/webview/common/webviewPortMapping.ts` | ソース | ポートマッピング |
| webview.ts (common) | `src/vs/workbench/contrib/webview/common/webview.ts` | ソース | 共通定義 |
| webview.contribution.ts | `src/vs/workbench/contrib/webview/browser/webview.contribution.ts` | ソース | 機能登録 |
| webviewMessages.d.ts | `src/vs/workbench/contrib/webview/browser/webviewMessages.d.ts` | 型定義 | メッセージ型定義 |
