Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions internal/camoufoxnative/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"strings"
)

// pageDOMHelpers 定义官网页面共用的可见目标与按钮状态判断
Expand All @@ -25,6 +26,11 @@ const promptReadyExpression = `(() => {` + pageDOMHelpers + `
// workerPageReadyExpression 等待输入框出现或页面跳转到登录入口
const workerPageReadyExpression = `(location.hostname === 'accounts.google.com' || ` + promptReadyExpression + `)`

// normalizePromptNewlines 把 CRLF/CR 统一成 LF,官网 textarea 会把写入值规范化为 LF
func normalizePromptNewlines(value string) string {
return strings.ReplaceAll(strings.ReplaceAll(value, "\r\n", "\n"), "\r", "\n")
}

// fillPromptExpression 向当前可见提示框写入文本并通知页面表单
func fillPromptExpression(prompt string) string {
encoded, _ := json.Marshal(prompt)
Expand Down
38 changes: 38 additions & 0 deletions internal/camoufoxnative/page_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package camoufoxnative

import "testing"

// TestNormalizePromptNewlines 覆盖官网 textarea 把写入值规范化为 LF 的比较场景
func TestNormalizePromptNewlines(t *testing.T) {
cases := []struct {
name string
value string
want string
}{
{name: "lf", value: "a\nb", want: "a\nb"},
{name: "crlf", value: "a\r\nb", want: "a\nb"},
{name: "cr", value: "a\rb", want: "a\nb"},
{name: "mixed", value: "a\r\nb\nc\rd", want: "a\nb\nc\nd"},
{name: "empty", value: "", want: ""},
{name: "no newline", value: "abc", want: "abc"},
}
for _, item := range cases {
t.Run(item.name, func(t *testing.T) {
if got := normalizePromptNewlines(item.value); got != item.want {
t.Fatalf("normalizePromptNewlines(%q) = %q, want %q", item.value, got, item.want)
}
})
}
}

// TestNormalizePromptNewlinesMatchesTextareaValue 确认 CRLF 提示词与官网返回的 LF 值判定为同步
func TestNormalizePromptNewlinesMatchesTextareaValue(t *testing.T) {
prompt := "line1\r\nline2\r\nline3"
textarea := "line1\nline2\nline3"
if prompt == textarea {
t.Fatal("用例前提失效: CRLF 提示词不应与 textarea 值直接相等")
}
if normalizePromptNewlines(prompt) != normalizePromptNewlines(textarea) {
t.Fatal("CRLF 提示词与 textarea LF 值应判定为已同步")
}
}
4 changes: 2 additions & 2 deletions internal/camoufoxnative/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (worker *Worker) Proof(ctx context.Context, digest string, prompt string) (
if err != nil {
return "", fmt.Errorf("同步官网 prompt: %w", err)
}
if value == prompt {
if normalizePromptNewlines(value) == normalizePromptNewlines(prompt) {
break
}
if time.Now().After(deadline) {
Expand Down Expand Up @@ -249,7 +249,7 @@ func (worker *Worker) bootstrap(ctx context.Context, options Options, storage st
}
options.reportStartup(StartupBootstrappingWAA)
filled, err := client.evaluateString(ctx, contextID, fillPromptExpression(options.BootstrapPrompt))
if err != nil || filled != options.BootstrapPrompt {
if err != nil || normalizePromptNewlines(filled) != normalizePromptNewlines(options.BootstrapPrompt) {
return fmt.Errorf("填写 bootstrap 提示词失败 value=%q err=%v", filled, err)
}
if _, err := client.command(ctx, "session.subscribe", map[string]any{
Expand Down