# Cookie 工作階段

`SameSession` 如何解密本機 Chrome 設定檔的 Cookie 並注入一次性瀏覽器，以讀取需登入的頁面。

## 用法

```go
result, err := browser.Fetch(ctx, "https://example.com/profile", 60*time.Second, &browser.Option{
	SameSession: true,
	Profile:     "Default",
})
```

原本的 Chrome 完全不受影響：Cookie 資料庫先複製到暫存目錄，載入頁面的瀏覽器跑在這份副本上。`Profile` 是 Chrome 設定檔根目錄下的子目錄名（`Default`、`Profile 1`……）。

## 流程

```mermaid
graph TB
    A[launchWithSnapshot] --> B[複製 Cookies / -wal / -shm 至暫存目錄]
    B --> C[取 Chrome Safe Storage 密碼]
    C --> D[PBKDF2-SHA1 推導 16 bytes 金鑰]
    D --> E[sqlite3 讀出 cookies]
    E --> F[AES-128-CBC 解密 v10 前綴值]
    F --> G[啟動暫存 profile 的 Chrome]
    G --> H[SetCookies 注入]
```

## 解密與注入

| 參數 | 值 |
|---|---|
| 密碼來源（macOS） | `security find-generic-password -w -s "Chrome Safe Storage" -a Chrome` |
| 密碼來源（Linux） | `secret-tool lookup application chrome`，再試 `application chromium` |
| 金鑰推導 | PBKDF2-SHA1，salt `saltysalt`，1003 次迭代，16 bytes 金鑰 |
| 加密演算法 | AES-128-CBC，IV 為 16 個空白字元，PKCS#7 padding |
| 加密標記 | `v10` 前綴；沒有前綴的值直接使用 |
| 明文前綴 | 解密後去掉前 32 bytes |

`cookies` 資料表每一列轉成一筆 CDP cookie，含 domain、path、到期時間（由 WebKit epoch 換算）、`Secure`、`HTTPOnly`、`SameSite`。解碼失敗的列直接略過。

### 注入

缺 domain 或 name 的 Cookie 會被丟棄，空 path 補成 `/`。批次注入失敗時改逐筆注入，只要有一筆成功就繼續；全部失敗回傳 `inject cookies (0/N)`。

## 失敗行為

| 情況 | 結果 |
|---|---|
| 無法判定設定檔根目錄（非 macOS／Linux）或 `Profile` 目錄不存在 | 改用不帶 Cookie 的一般快取瀏覽器 |
| 鑰匙圈、`secret-tool`、`sqlite3` 或啟動失敗 | 直接回傳錯誤，不降級 |
| 工作階段結束 | 關閉瀏覽器並刪除暫存目錄，出錯時也一樣 |

路由仍然適用：`SameSession` 呼叫被擋時可以有頭重試，每次嘗試各自建立暫存設定檔。見 [Fetch 路由](/zh/core-concepts-routing)。
