7 min
AGENT SPEC: firefox address-bar grok send
Agent spec. Keep engine 805b8ce4-df7b-4179-a54f-50597d19e8af. Click Send iff webNavigation transitionType is generated or keyword and from_address_bar is set.
Audience is an agent. Apply this file. Do not replace it with prose.
Confirmed behavior at addon version 1.0.3: an address-bar query submits and the confirm dialog does not paint. Leave content.js and background.js unchanged unless the user asks for a behavior change.
end state
- Firefox release address bar and
@groksubmit tohttps://grok.com/?q={searchTerms}. - Confirm dialog is clicked only for those navigations.
- Pasted
grok.com/?q=URLs, bookmarks, and clicked links keep the dialog. The message is not sent.
click predicate
All of the following. Top frame only (frameId 0).
transitionQualifierscontainsfrom_address_bartransitionTypeisgeneratedorkeywordhttps- host is
grok.comorwww.grok.com qis non-empty
| start | transitionType | from_address_bar | click |
|---|---|---|---|
| address-bar search | generated | yes | yes |
@grok keyword |
keyword | yes | yes |
| pasted URL | typed | yes | no |
| bookmark | auto_bookmark | yes | no |
| clicked link | link | no | no |
| client_redirect or server_redirect | any | any | keep the tab flag |
| any other top-level navigation | any | any | clear the tab flag |
Tag source: WebNavigation.sys.mjs onURLBarUserStartNavigation. Readable only by the extension on webNavigation.onBeforeNavigate and webNavigation.onCommitted. Page JS cannot read it. Trust the background record. Do not infer the address bar from referrer, Sec-Fetch-Site, or a URL flag.
bindings
firefox.binary: /usr/lib/firefox/firefox
firefox.wrapper: /usr/bin/firefox
firefox.version: 157.0.1
firefox.channel: release
app.id: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
profile: /home/moji/.mozilla/firefox/xoybst8z.default-release-1710381840470
installs.ini: Install4F96D1932A9F858E
profile.user.js: extensions.startupScanScopes = 4
vendor.js: /usr/lib/firefox/browser/defaults/preferences/vendor.js
vendor.autoDisableScopes: 11
browser.startup.page: 3
MOZ_REQUIRE_SIGNING: true
MOZ_UNSIGNED_APP_SCOPE: true
MOZ_UNSIGNED_SYSTEM_SCOPE: true
MOZ_ALLOW_ADDON_SIDELOAD: true
xpinstall.signatures.required=false: ignored
SCOPE_PROFILE: 1
SCOPE_USER: 2
SCOPE_APPLICATION: 4
SCOPE_SYSTEM: 8
XREAddonAppDir: /usr/lib/firefox/browser
scan_dir: /usr/lib/firefox/browser/extensions
engine.id: 805b8ce4-df7b-4179-a54f-50597d19e8af
engine.name: Grok
engine.template: https://grok.com/?q={searchTerms}
engine.keyword: @grok
engine._loadPath: [user]
engine.defaultEngineId: 805b8ce4-df7b-4179-a54f-50597d19e8af
engine.privateDefaultEngineId: 805b8ce4-df7b-4179-a54f-50597d19e8af
engine.appDefault: google
search.file: <profile>/search.json.mozlz4
search.backup: <profile>/search.json.mozlz4.bak-before-grok
search.format: mozLz40 NUL + uint32le uncompressed size + raw LZ4
addon.id: grok-address-bar-send@moji.local
addon.version: 1.0.3
addon.source: /home/moji/.local/share/grok-address-bar-send
addon.pointer: /usr/lib/firefox/browser/extensions/grok-address-bar-send@moji.local
addon.pointer.bytes: /home/moji/.local/share/grok-address-bar-send\n
addon.pointer.mode: regular file 644 root. not a symlink
addon.location: app-global
addon.permissions: [webNavigation]
addon.origins: [https://grok.com/*, https://www.grok.com/*]
content_scripts.run_at: document_start
event: grok-address-bar-submit
event.detail: { source: "firefox-address-bar", transition }
messages: grok-bar-check, grok-bar-done
dialog.selector: [data-analytics-name="link-query-confirm-dialog"]
dialog.heading: /send this message/i
send.control: /^send$/i on trimmed text or aria-label
dialog.wait_ms: 20000
dialog.poll_ms: 100
dialog.reclick_ms: 400
check.retries_when_q: 8
check.gap_ms: 40
check.retries_without_q: 1
private_browsing: absent. no internal:privateBrowsingAllowed
stale_pointer_not_scanned: /usr/lib/firefox/extensions/grok-address-bar-send@moji.local
invariants
- Do not put the query text in the event, a hash, or a query flag.
- grok.com does not listen for
grok-address-bar-submit. The click sends. - Click only the enabled Send control inside the confirm dialog. Walk open shadow roots. Call
button.wrappedJSObject.click(). - Do not click
button[aria-label="Submit"]or[data-testid="chat-submit"]. - Success is the dialog node absent. A returned function is not success.
- Second click only if the dialog is still present 400ms later.
- On timeout, disconnect the observer and do not send
grok-bar-done. - Send
grok-bar-doneonly after the dialog is gone, then clear the tab flag. Also clear ontabs.onRemoved. - A thrown
sendMessageis a retry. - Dispatch the event with
window.wrappedJSObjectandcloneInto. An inline script is blocked by the grok.com CSP nonce. - Do not reimplement the conversation API. The Send
onClicksubmits withlinkQuery: true,disableMemory: true,disablePersonalization: true. It ignores the event argument.isTrustedis not checked. - Do not stop React from opening the dialog. Click in the same animation frame the node is inserted.
- Logged-in grok.com opens the dialog only after subscriptions leave pending. Cover that delay. Anonymous sessions are not delayed by that check.
- Do not rewrite
search.json.mozlz4while both engine ids equalengine.id. A bad verification hash resets the default toappDefaultgoogle. Leavesearch.json.mozlz4.bak-before-grokin place. - Do not install under the profile
extensions/directory,~/.mozilla/extensions/,/usr/lib/firefox/extensions, or/usr/lib/mozilla/extensions/{app.id}/. - Do not grant
<all_urls>. - Do not remove
extensions.startupScanScopes4 from profileuser.js. - Do not edit
prefs.jsorextension-preferences.jsonwhile Firefox is running. - Do not leave remote debugging or
MOZ_AUTOMATIONon. - Do not edit
extensions.jsonuntil an addon row exists. browser.startup.pageis 3. Restart Firefox only when a code or permission change must load. One process. Do not use this profile for experiments.- Do not use a pasted
?q=load as proof the click works. - Private windows do not run this addon until the user enables Run in Private Windows. Do not add a policies.json for that unless the user asks. A managed-browser banner is the result.
- The
user.jscomment names/usr/lib/firefox/extensions. Ignore the comment. The pref value 4 is the scanned scope. The scanned directory isscan_dir. - The stale pointer is inert. Do not add a second live copy. Deleting it needs root. Not required.
- Bump
manifest.jsonversionwhen JS changes. Sideload does not hot-reload.
background
Map tabId to { transition, at }.
On onBeforeNavigate and onCommitted, frameId 0:
- predicate matches: set the tab
- else qualifiers contain
client_redirectorserver_redirect: keep - else: delete
grok-bar-check returns { addressBar: true, transition } or { addressBar: false }.
grok-bar-done deletes the tab.
content
Run at document_start.
- If the document URL has
q, callgrok-bar-checkup to 8 times, 40ms apart. Otherwise once. A throw sets the answer null and continues. - If
addressBaris false, return. - Dispatch
grok-address-bar-submiton the page window. Detail isevent.detailonly. MutationObserverondocument.documentElement:childList,subtree, attributesdata-analytics-name,data-state,role,disabled. On mutation,requestAnimationFramethen tryClick.setIntervaltryClick every 100ms.setTimeout20000ms stops the observer and the interval.- tryClick: if a click already happened and the dialog is gone, send
grok-bar-doneand stop. If a click happened less than 400ms ago, return. Otherwise click Send. - Find the dialog:
dialog.selector, else[role=dialog],[role=alertdialog], or[aria-modal=true]whose text matchesdialog.heading, else a heading matching that pattern and its closest dialog or parent. - Send control:
buttonor[role=button]under that root, including shadow roots, not disabled, text oraria-labelmatchingsend.control.
install
Source directory is user-owned, mode 644: manifest.json, background.js, content.js. Gecko id equals addon.id and the pointer filename. strict_min_version 128.0. gIDTest accepts this id.
Pointer file leaf name is addon.id. First line is the absolute source path plus newline.
4 & autoDisableScopes 11 == 0, so a new application-scope addon starts enabled. Unsigned application scope is SIGNEDSTATE_NOT_REQUIRED.
extensions.startupScanScopes defaults to 0 when extensions.lastAppBuildId is unchanged. Empty locations are omitted from addonStartup.json.lz4. The user.js pref is what makes the next source mtime scan.
MV3 host_permissions are optional origins and are not auto-granted on a future reinstall. The live grant is profile extension-preferences.json for addon.id:
{"permissions":[],"origins":["https://grok.com/*","https://www.grok.com/*"],"data_collection":[]}
If those origins are missing, the content script does not run. Re-grant those two origins only.
reload
Quit with SIGTERM on the single /usr/lib/firefox/firefox pid. The parent is systemd --user. Plasma does not relaunch it.
Restart with setsid. Copy DISPLAY, XAUTHORITY, XDG_RUNTIME_DIR, DBUS_SESSION_BUS_ADDRESS, and DESKTOP_SESSION from the old process environ. Do not start a second instance.
Then require all of:
- one firefox pid
extensions.json: this id,activetrue,userDisabledfalse,appDisabledfalse,locationapp-global,versionequals the manifestaddonStartup.json.lz4:app-globalpathscan_dir, addon enabledextension-preferences.jsonorigins equaladdon.origins- both engine ids still
engine.id
verify
- Address-bar Enter reaches Grok and the confirm dialog does not remain.
- A bookmark or a pasted
https://grok.com/?q=teststill shows the dialog and does not send. - Both engine ids are unchanged.
- One firefox pid.
reject
- Profile or user scope. Release requires a Mozilla signature.
xpinstall.signatures.required=falsedoes nothing. - System scope
/usr/lib/mozilla/extensions/{app.id}/.8 & 11 != 0, so it installs disabled. /usr/lib/firefox/extensions. This binary does not scan it.KEY_APP_GLOBALisscan_dir.- Headless without
-no-remoteattaches to the running browser and exits. Do not use it as an install test on this profile. - Treating a page React
onClickcall as success. The watcher stops while the dialog is still open. - Aborting the address-bar check on the first
sendMessagethrow. - A
#gwc=token or any other page-side secret. Any link can forge it. - Clicking Send for every
?q=load.