Skip to content
Closed
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).

### Fixed

- Bundled Browser plugin staging now preserves `file://` URL support advertised
by the Browser plugin while keeping `data:` URLs blocked by the upstream URL
policy.
- `codex-update-manager` now prunes unreferenced updater workspaces under `~/.cache/codex-update-manager/workspaces`, removing heavy build artifacts (`builder/`, `codex-app/`, `dist/`) while preserving lightweight diagnostics such as `logs/` and rebuild reports.
- The Chrome native-messaging host now evicts stale browser clients when a newer Codex browser client connects, preventing old Node REPL sessions from repeatedly reattaching CDP and driving extension service-worker CPU.
- The bundled Chrome plugin is now auto-installed during app startup, matching Browser Use, so the plugin page no longer falls back to an install button after restart when the Linux native host is already staged.
Expand Down
46 changes: 46 additions & 0 deletions scripts/lib/bundled-plugins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,51 @@ path.write_text(source[:match.start()] + replacement + source[match.end():], enc
PY
}

patch_browser_use_file_url_policy() {
local client="$1"

if grep -q "codexLinuxFileUrlPolicy" "$client"; then
return 0
fi

python3 - "$client" <<'PY'
from pathlib import Path
import re
import sys

path = Path(sys.argv[1])
source = path.read_text(encoding="utf-8")
pattern = re.compile(
r'function\s+(?P<helper>[A-Za-z_$][\w$]*)\((?P<url>[A-Za-z_$][\w$]*)\)\{'
r'if\((?P<allowlist>[A-Za-z_$][\w$]*)\.has\((?P=url)\)\)return\s*(?:true|!0);'
r'(?:const|let|var)\s+(?P<parsed>[A-Za-z_$][\w$]*)=new URL\((?P=url)\);'
r'return\s+(?P=parsed)\.protocol\s*===\s*"http:"\s*\|\|\s*'
r'(?P=parsed)\.protocol\s*===\s*"https:"(?P<semicolon>;?)\}'
)
match = pattern.search(source)
if match is None:
print(
"WARN: Could not find Browser Use URL policy insertion point — leaving browser-client.mjs unchanged",
file=sys.stderr,
)
raise SystemExit(0)

parsed = match.group("parsed")
semicolon = match.group("semicolon")
old_body = match.group(0)
old_return = re.compile(
rf'return\s+{re.escape(parsed)}\.protocol\s*===\s*"http:"\s*\|\|\s*'
rf'{re.escape(parsed)}\.protocol\s*===\s*"https:"{re.escape(semicolon)}'
)
new_return = (
f'return {parsed}.protocol==="http:"||{parsed}.protocol==="https:"||'
f'{parsed}.protocol==="file:"/*codexLinuxFileUrlPolicy*/{semicolon}'
)
new_body = old_return.sub(new_return, old_body, count=1)
path.write_text(source[:match.start()] + new_body + source[match.end():], encoding="utf-8")
PY
}

patch_browser_use_node_repl_env_guard() {
local client="$1"

Expand Down Expand Up @@ -789,6 +834,7 @@ stage_browser_plugin_from_upstream() {
patch_browser_use_node_repl_env_guard "$target_client"
patch_browser_use_native_pipe_import_meta_bridge "$target_client"
patch_browser_use_site_status_allowlist_fallback "$target_client"
patch_browser_use_file_url_policy "$target_client"

info "Browser plugin staged from upstream DMG"
return 0
Expand Down
6 changes: 5 additions & 1 deletion tests/scripts_smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ JSON
{"name":"browser","version":"0.1.0-alpha2","interface":{"category":"Engineering"}}
JSON
cat > "$resources_dir/plugins/openai-bundled/plugins/browser/scripts/browser-client.mjs" <<'JS'
function lu(e){let t=globalThis.nodeRepl?.env[e];return typeof t=="string"?t:void 0}function th(){let e=import.meta.__codexNativePipe;return e==null||typeof e.createConnection!="function"?null:e}class Uf{async fetchBlocked(e){let r=await bS(e.endpoint,{method:"GET"});if(!r.ok)throw new Error(ae(`Browser Use cannot determine if ${e.displayUrl} is allowed. Please try again later or use another source.`));let n=await r.json();return TF(n)}}export function setupAtlasRuntime() {}
function lu(e){let t=globalThis.nodeRepl?.env[e];return typeof t=="string"?t:void 0}function th(){let e=import.meta.__codexNativePipe;return e==null||typeof e.createConnection!="function"?null:e}var Z6=new Set(["about:blank"]);function Qv(e){if(Z6.has(e))return true;const t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}class Uf{async fetchBlocked(e){let r=await bS(e.endpoint,{method:"GET"});if(!r.ok)throw new Error(ae(`Browser Use cannot determine if ${e.displayUrl} is allowed. Please try again later or use another source.`));let n=await r.json();return TF(n)}}export function setupAtlasRuntime() {}
JS
}

Expand Down Expand Up @@ -2396,6 +2396,7 @@ test_browser_use_node_repl_fallback_runtime() {
assert_contains "$install_dir/resources/plugins/openai-bundled/plugins/browser/scripts/browser-client.mjs" 'globalThis.nodeRepl?.env?.\[e\]'
assert_not_contains "$install_dir/resources/plugins/openai-bundled/plugins/browser/scripts/browser-client.mjs" 'globalThis.nodeRepl?.env\[e\]'
assert_contains "$install_dir/resources/plugins/openai-bundled/plugins/browser/scripts/browser-client.mjs" "codexLinuxSiteStatusAllowlistFallback"
assert_contains "$install_dir/resources/plugins/openai-bundled/plugins/browser/scripts/browser-client.mjs" "codexLinuxFileUrlPolicy"
assert_contains "$output_log" "Browser Use node_repl runtime is not a Linux executable for x86_64; skipping"
assert_not_contains "$output_log" "WARN.*Browser Use node_repl runtime is not a Linux executable"
assert_contains "$output_log" "Downloading Browser Use node_repl fallback runtime"
Expand Down Expand Up @@ -2437,6 +2438,9 @@ test_browser_plugin_renamed_upstream_staging() {
assert_contains "$browser_dir/scripts/browser-client.mjs" "nativePipe??import.meta.__codexNativePipe"
assert_not_contains "$browser_dir/scripts/browser-client.mjs" "let e=import.meta.__codexNativePipe;return"
assert_contains "$browser_dir/scripts/browser-client.mjs" "codexLinuxSiteStatusAllowlistFallback"
assert_contains "$browser_dir/scripts/browser-client.mjs" "codexLinuxFileUrlPolicy"
assert_contains "$browser_dir/scripts/browser-client.mjs" 'protocol==="file:"'
assert_not_contains "$browser_dir/scripts/browser-client.mjs" 'protocol==="data:"'
assert_contains "$marketplace" '"name": "browser"'
assert_contains "$marketplace" '"path": "./plugins/browser"'
assert_contains "$output_log" "Browser plugin staged from upstream DMG"
Expand Down
Loading