feat!: harden raw browser control and packaging
Testing / remote-protocol-compat (0.9.3) (push) Successful in 40s
Testing / remote-protocol-compat (0.9.5) (push) Successful in 38s
Testing / test (push) Failing after 1m3s
Package Extension / package-extension (push) Successful in 29s
Build & Publish Package / publish (push) Successful in 33s
Testing / remote-protocol-compat (0.9.3) (push) Successful in 40s
Testing / remote-protocol-compat (0.9.5) (push) Successful in 38s
Testing / test (push) Failing after 1m3s
Package Extension / package-extension (push) Successful in 29s
Build & Publish Package / publish (push) Successful in 33s
- Add safe-by-default policy gates for raw command surfaces: command, script, and serve-http /command. - Require explicit opt-ins for page reads, browser control, and high-risk commands such as dom.eval, storage.*, and screenshots. - Remove all cookies support from CLI, SDK, extension commands, permissions, constants, docs, and tests. - Add diagnostic, events, watch, workspace, remote, raw command, script, HTTP gateway, tree-view, session import/export, and extension info/capability commands. - Add Chrome Web Store packaging that strips manifest.key while keeping local packages with a stable native-messaging extension ID. - Bump browser-cli and extension version to 0.14.1 and cover the new behavior with pytest and extension packaging tests. BREAKING CHANGE: cookies commands and the b.cookies SDK namespace have been removed; generic raw command execution now blocks non-safe commands unless explicitly allowed.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import time
|
||||
|
||||
import click
|
||||
|
||||
from browser_cli.commands import client_from_ctx, handle_errors
|
||||
|
||||
@click.group("watch")
|
||||
def watch_group():
|
||||
"""Watch browser state and print changes."""
|
||||
|
||||
@watch_group.command("tabs")
|
||||
@click.option("--interval", type=float, default=1.0, show_default=True)
|
||||
@click.option("--once", is_flag=True)
|
||||
@handle_errors
|
||||
def watch_tabs(interval, once):
|
||||
"""Watch the tab list as JSON snapshots."""
|
||||
client = client_from_ctx()
|
||||
previous = None
|
||||
while True:
|
||||
current = [t.__dict__ for t in client.tabs.list()]
|
||||
if current != previous:
|
||||
click.echo(json.dumps({"type": "tabs", "tabs": current}, default=str), flush=True)
|
||||
previous = current
|
||||
if once:
|
||||
return
|
||||
time.sleep(interval)
|
||||
|
||||
@watch_group.command("page")
|
||||
@click.option("--field", default=None, help="Only print a single page.info field")
|
||||
@click.option("--interval", type=float, default=1.0, show_default=True)
|
||||
@handle_errors
|
||||
def watch_page(field, interval):
|
||||
"""Watch page.info for the active tab."""
|
||||
client = client_from_ctx()
|
||||
previous = object()
|
||||
while True:
|
||||
info = client.page.info()
|
||||
current = info.get(field) if field else info
|
||||
if current != previous:
|
||||
click.echo(json.dumps({"type": "page", "field": field, "value": current}, default=str), flush=True)
|
||||
previous = current
|
||||
time.sleep(interval)
|
||||
|
||||
@watch_group.command("dom")
|
||||
@click.argument("selector")
|
||||
@click.option("--interval", type=float, default=1.0, show_default=True)
|
||||
@handle_errors
|
||||
def watch_dom(selector, interval):
|
||||
"""Watch textContent for a selector."""
|
||||
client = client_from_ctx()
|
||||
previous = object()
|
||||
while True:
|
||||
current = client.dom.text(selector)
|
||||
if current != previous:
|
||||
click.echo(json.dumps({"type": "dom", "selector": selector, "text": current}, default=str), flush=True)
|
||||
previous = current
|
||||
time.sleep(interval)
|
||||
Reference in New Issue
Block a user