# 機能設計書 105-browsers

## 概要

本ドキュメントは、Nim標準ライブラリの`browsers`モジュールの機能設計を記述する。このモジュールは、ユーザーのデフォルトブラウザでURLを開く機能を提供する。

### 本機能の処理概要

`browsers`モジュールは、クロスプラットフォームでユーザーのデフォルトWebブラウザを使用してURLを開くための機能を提供する。Windows、macOS、Linux/Unixの各プラットフォームに対応した実装を持つ。

**業務上の目的・背景**：アプリケーション開発において、ヘルプページ、ドキュメント、外部サービスへのリンクをブラウザで開く必要がある場面は多い。各OSで異なるブラウザ起動方法を抽象化し、統一的なAPIを提供することで、クロスプラットフォーム開発を簡素化する。

**機能の利用シーン**：ヘルプドキュメントの表示、OAuth認証フロー（ブラウザでの認証画面表示）、外部Webサービスへのリダイレクト、HTMLレポートの表示など。

**主要な処理内容**：
1. URLをデフォルトブラウザで開く（`openDefaultBrowser`）
2. プラットフォーム固有の「open」コマンドの抽象化

**関連システム・外部連携**：OS固有のシェルコマンド（Windows: ShellExecute、macOS: open、Linux: xdg-open）との連携。

**権限による制御**：権限による制御は存在しないが、OS側のセキュリティポリシーに依存。

## 関連画面

本モジュールは標準ライブラリであり、特定の画面との関連はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

外部連携 / システムユーティリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| url | string | Yes | 開くURL | 空文字列不可、URLまたはファイルパス |

### 入力データソース

プログラムコードからの直接呼び出し。

## 出力仕様

### 出力データ

本関数は戻り値を返さない（void）。ブラウザ起動は非同期で行われる。

| 項目名 | 型 | 説明 |
|--------|-----|------|
| - | - | 戻り値なし |

### 出力先

システムのデフォルトブラウザ。

## 処理フロー

### 処理シーケンス

```
1. URL準備 (prepare)
   └─ "://"が含まれていれば、そのまま使用
   └─ 含まれていなければ、"file://"を付加し絶対パスに変換

2. ブラウザ起動 (openDefaultBrowserRaw)
   └─ Windowsの場合: ShellExecuteW
   └─ macOSの場合: execShellCmd("open " + url)
   └─ Linux/Unixの場合:
       ├─ xdg-openを試行
       └─ 失敗時はBROWSER環境変数のブラウザを試行
```

### フローチャート

```mermaid
flowchart TD
    A[開始: openDefaultBrowser] --> B{URLが空?}
    B -->|Yes| C[doAssert失敗]
    B -->|No| D[prepare関数]
    D --> E{"://含む?"}
    E -->|Yes| F[そのまま使用]
    E -->|No| G[file:// + absolutePath]
    F --> H{プラットフォーム判定}
    G --> H
    H -->|Windows| I[ShellExecuteW]
    H -->|macOS| J[execShellCmd open]
    H -->|Linux| K[xdg-open試行]
    K --> L{成功?}
    L -->|Yes| M[終了]
    L -->|No| N[BROWSER環境変数で試行]
    N --> M
    I --> M
    J --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | URL必須 | 空文字列のURLは許可されない | openDefaultBrowser(url)呼び出し時 |
| BR-02 | プロトコル補完 | "://"が含まれないパスには"file://"を付加 | prepare関数実行時 |
| BR-03 | 非ブロッキング | ブラウザ起動は非同期で行われ、呼び出し元はブロックされない | 常時 |
| BR-04 | エラー非発生 | エラー発生時も例外を投げない | 常時 |

### 計算ロジック

**プロトコル補完（prepare関数）**:
```nim
if s.contains("://"):
  result = s
else:
  result = "file://" & absolutePath(s)
```

**プラットフォーム別コマンド**:
- Windows/macOS: `"open"`
- Linux/BSD: `"xdg-open"`

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

本モジュールはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| AssertionDefect | アサーション失敗 | 空文字列のURLを渡した場合 | 有効なURLを指定 |

### リトライ仕様

Linux/Unix環境では、xdg-openが失敗した場合にBROWSER環境変数で指定されたブラウザを試行。

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

トランザクション管理は不要。

## パフォーマンス要件

- ブラウザ起動は非同期（非ブロッキング）
- startProcessを使用してバックグラウンドで起動

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

- 任意のURLを開くため、悪意のあるURLを開かないよう注意
- quoteShellを使用してシェルインジェクションを防止

## 備考

- APIは「Unstable」としてマークされている
- 引数なしの`openDefaultBrowser()`はdeprecated（about:blankを開く意図だが未実装）

---

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

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

### 推奨読解順序

#### Step 1: プラットフォーム判定を理解する

条件コンパイルによるプラットフォーム分岐を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | browsers.nim | `lib/pure/browsers.nim` | 22-30行目: プラットフォーム別import |
| 1-2 | browsers.nim | `lib/pure/browsers.nim` | 32-35行目: osOpenCmd定数 |

**読解のコツ**: `when defined(windows):`や`when defined(macos):`で条件コンパイルが行われている。osOpenCmdは各プラットフォームで異なる値を持つ定数。

#### Step 2: URL準備処理を理解する

prepare関数でのURL正規化を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | browsers.nim | `lib/pure/browsers.nim` | 37-41行目: prepare関数 |

**主要処理フロー**:
- **38行目**: URLに"://"が含まれるかチェック
- **39行目**: 含まれていればそのまま返却
- **41行目**: 含まれていなければfile://プロトコルと絶対パスを付加

#### Step 3: ブラウザ起動処理を理解する

各プラットフォームでのブラウザ起動実装を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | browsers.nim | `lib/pure/browsers.nim` | 43-61行目: openDefaultBrowserRaw関数 |

**主要処理フロー**:
- **46-49行目**: Windows - ShellExecuteWを使用
- **50-51行目**: macOS - execShellCmdでopenコマンド実行
- **52-61行目**: Linux/Unix - xdg-openを試行、失敗時はBROWSER環境変数

#### Step 4: 公開API関数を理解する

ユーザー向け関数の実装を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | browsers.nim | `lib/pure/browsers.nim` | 63-78行目: openDefaultBrowser(url)関数 |
| 4-2 | browsers.nim | `lib/pure/browsers.nim` | 80-112行目: openDefaultBrowser()関数（deprecated） |

**主要処理フロー**:
- **77行目**: URLが空でないことをassert
- **78行目**: openDefaultBrowserRawを呼び出し
- **80行目**: 引数なし版はdeprecatedとしてマーク

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

```
browsers.nim
    │
    ├─ 定数
    │      └─ osOpenCmd ("open" or "xdg-open")
    │
    ├─ 内部関数
    │      ├─ prepare ─── contains("://") + absolutePath
    │      └─ openDefaultBrowserRaw
    │              │
    │              ├─ [Windows] ShellExecuteW
    │              ├─ [macOS] execShellCmd
    │              └─ [Linux] xdg-open / BROWSER環境変数
    │
    └─ 公開API
           └─ openDefaultBrowser(url) ─── prepare ─── openDefaultBrowserRaw
```

### データフロー図

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

URL文字列 ──────────────▶ prepare ──────────────────▶ 正規化URL
                              │
                              ├─ "://"含む → そのまま
                              └─ 含まない → "file://" + absolutePath

正規化URL ──────────────▶ openDefaultBrowserRaw ────▶ ブラウザ起動
                              │
                              ├─ [Windows] ShellExecuteW
                              ├─ [macOS] execShellCmd("open")
                              └─ [Linux] xdg-open / startProcess(BROWSER)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| browsers.nim | `lib/pure/browsers.nim` | ソース | メインモジュール、全機能の実装 |
| strutils.nim | `lib/pure/strutils.nim` | 依存 | contains関数 |
| os.nim | `lib/pure/os.nim` | 依存 | absolutePath、getEnv、execShellCmd |
| osproc.nim | `lib/pure/osproc.nim` | 依存 | startProcess（Linux用） |
| winlean.nim | `lib/pure/winlean.nim` | 依存 | ShellExecuteW（Windows用） |
| widestrs.nim | `lib/std/widestrs.nim` | 依存 | newWideCString（Windows用） |
| since.nim | `lib/std/private/since.nim` | 依存 | since pragma |
