# Advanced context menu design Status: agreed conversational design, awaiting written-spec review. ## Purpose and scope Preserve today's quick selection action while offering an optional advanced menu with useful built-in prompts. Adapt the advanced menu to selected text, links, or the current page. Translation is useful but optional, so it is hidden until enabled. Firefox Desktop remains the only target. This work includes settings migration, contextual menus, dedicated prompts, translation and truncation dialogs, documentation, and tests. It does not include custom action editing, full-page extraction, model/effort selection, omnibox changes, MV3 migration, containers, or automatic submission. ## Settings and migration Replace the existing context-menu checkbox with **Context menu**: - **Off:** no extension context menu. - **Simple:** today's direct **Ask ChatGPT** item, only for selected text. - **Advanced:** one **Ask ChatGPT** submenu with contextual actions. Only the selected menu variant is visible; do not leave the other grayed out. The keyboard shortcut continues to run the default selection action in every mode, including Off, and opens a blank chat when no selection is available. New settings in the existing sync storage: | Key | Values | Default | | --- | --- | --- | | `contextMenuMode` | `off`, `simple`, `advanced` | `simple` | | `showTranslate` | Boolean | `false` | | `translationMode` | `ask`, `preferred` | `ask` | | `translationLanguage` | Trimmed free text, maximum 100 Unicode code points | Empty | Retain existing temporary-chat, web-search, open-location, and prompt-template settings. Read the legacy `showContextMenu` key during migration even though it is no longer in the new defaults. A valid new mode takes precedence; otherwise legacy false maps to Off and legacy true or absence maps to Simple. A subsequent save writes the new mode. Invalid stored values fall back safely. Advanced mode reveals **Show Translate in advanced menu**, initially unchecked. When checked, reveal **Translate into** with **Ask each time** and **Preferred language**. Preferred language reveals a free-text field; it accepts Spanish or any other language without a fixed language list. Empty preferred language shows inline guidance and invokes the language dialog rather than constructing an incomplete prompt. Turning a feature off hides its controls but retains its preferences. Restore defaults resets all extension settings, including these, without changing Firefox's engine settings or keyboard shortcut. ## Context selection and menu layout Choose one group for each opening, in this priority order: 1. Nonempty selected text, including selection inside a link. 2. A clicked link when there is no selection. 3. Page background when there is no selection or link. Do not add special image, video, password-field, or browser-chrome actions. Native editable-field behavior must be checked in Firefox before claiming it is supported. Use menu event data for selection and URLs; no background page scraping or automatic navigation to the linked site. | Context | Children, in order | | --- | --- | | Selection | Ask normally; separator; Explain; Summarize; Debug code; Translate when enabled | | Link | Ask about this link; Review link safety | | Page | Ask about this page; Summarize this page | The selection presets are always present in Advanced mode except Translate. Do not infer whether text is code. Debug code appears for any selection and the user decides when it applies. With a valid preferred language, label the translation item **Translate to Spanish** (substituting the user's language); otherwise use **Translate…**. Escape menu-label access-key characters in user-supplied language names so the displayed text remains literal. Use Firefox menu visibility updates when the menu opens to enforce precedence, then refresh the native menu. Serialize registration and settings updates, as the existing implementation does. Validate click data again before launching; visibility is not input validation. ## Prompt behavior **Ask normally** and the keyboard shortcut apply the user's existing prompt template. Every other action uses its own dedicated prompt without appending or wrapping it in that template. All actions respect the existing open-location, temporary-chat, and web-search preferences. Hints retain their existing best-effort status. The address-bar search provider is unchanged. Dedicated prompts should express these instructions, followed by a clearly labeled source block: | Action | Instructions | | --- | --- | | Explain | Explain the selected text clearly, defining unfamiliar terms. | | Summarize | Summarize the selected text, preserving its main points and qualifications. | | Debug code | Identify likely problems and suggest fixes; explain the reasoning and ask for missing context when necessary. | | Translate | Translate the selected text into the specified language, preserving meaning and formatting where practical. | | Ask about link/page | Help the user understand the supplied URL, ask what they would like to know, and say if its content cannot be accessed. | | Review link safety | Review suspicious indicators and available evidence; distinguish URL inspection from checks actually performed, state uncertainty, and do not guarantee that the link is safe. | | Summarize page | Summarize the content at the URL; if it cannot be accessed, say so and ask the user to supply the text rather than inventing a summary. | Source text and URLs are data, not extension instructions. Explicit framing helps communicate this but is not a security boundary. Users still review and submit in ChatGPT; no auto-submit or internal ChatGPT request modification. Link/page actions share the relevant URL only, without reading page text or adding titles. Accept only HTTP(S) URLs. Reject malformed URLs, URLs containing embedded username/password credentials, and unsupported schemes with a clear message. Preserve accepted URLs intact, including their query/fragment rather than silently changing the destination. Documentation must explain that URLs can contain private information and are sent to ChatGPT by the chosen action. ## Translation and other dialogs Use a packaged extension dialog window, not a JavaScript prompt injected into the source page. Reuse one small dialog surface for language entry, truncation confirmation, and actionable errors, with appropriately distinct copy. For Ask each time, Translate focuses the language input. Enter with a nonempty trimmed language continues; Escape, Cancel, or closing the window cancels. The one-time language choice does not silently change the saved preference. Preferred language bypasses this dialog when valid. Do not put selected text or source URLs in the dialog URL or persistent/sync storage. Use an opaque request identifier and extension-internal messaging to transfer the pending action. Scope requests to their dialog, allow concurrent requests without mixing data, and release them on completion or cancellation. Keep the nonpersistent background lifecycle in mind: do not depend on a global Map surviving while the user types. Transfer the snapshot to the dialog through an initial handshake while the launch handler is active; after acknowledgment, the dialog owns its in-memory snapshot and can complete the launch itself. If initialization fails or context is lost, show a retry message and never send partial or mismatched input. Do not persist pending selections to survive a browser restart. Disable Continue while launching to prevent duplicate tabs. Capture the action, selected source, and settings together so later tab changes or preference updates do not alter an already-open dialog's operation. If the dialog window cannot open, attempt the same extension page in a tab. Launch failures within the dialog remain visible and allow retry or cancellation. ## Length limits and launch behavior Retain the current 8,000-character serialized URL budget. Preserve dedicated instructions and language in full; shorten only selected source text, on Unicode code-point boundaries with a whitespace boundary where practical. Include any shortening marker in the budget calculation. If even the instructions cannot fit, explain the problem instead of emitting a misleading prompt. When selected text must be shortened, show a brief confirmation before opening ChatGPT, with **Continue with shortened text** and **Cancel**. This applies to Simple, Advanced, and the keyboard shortcut so they share one launch contract. For Translate with Ask each time, calculate the final budget after language entry and present confirmation in the same dialog if needed. Never truncate a link/page URL: explain that it is too long and stop that action. On successful continuation, reuse new-tab, background-tab, and new-window behavior, including the existing new-window failure fallback to a tab. Close the dialog after a successful launch. Direct-launch failures should use the same error surface when it remains available; avoid silent success messages. ## Code boundaries - Pure modules under `lib/` own action definitions, prompt assembly, context selection, settings validation/migration, and budget calculations. No browser APIs in these modules. - The background owns Firefox menu registration/events and entry-point routing. - A shared browser-facing launch helper owns tab/window opening and fallback. - The packaged dialog owns input, confirmation, and its pending action after transfer; it uses the same pure prompt and URL logic as direct launches. - Options remain inline in `about:addons` and use existing visual styles. Preserve the current `storage`, `menus`, and `activeTab` permissions. No new host permissions, telemetry, intermediary service, runtime dependency, or API key is part of this design. Re-read the original options design and Appendix B before any proposed permission or submission change. A discovered inability to meet this constraint requires revisiting the design, not silently adding permissions. ## Verification and documentation Meaningful unit tests cover legacy migration/new-key precedence, invalid settings, context precedence, literal source substitution, dedicated-template isolation, language validation, URL validation, and encoded-length boundaries. Verify that long source truncation preserves instructions and that URLs are never partially sent. Test dialog state transitions and cancellation/duplicate submission behavior at browser boundaries where feasible. Run `npm test` with a nonzero test count. Inspect the built ZIP: include the dialog assets; exclude `test/` and `docs/`, including empty directory entries. Manual Firefox checks: - Off/Simple/Advanced updates immediately and persists; legacy users retain mode. - Selection, linked selection, bare link, and page background show the correct group with no duplicate or disabled alternate root. - All actions construct the intended prompts; keyboard shortcut remains default. - Translation visibility, preferred language, blank preferred fallback, Enter, Escape, Cancel, and closing the dialog behave as specified. - Concurrent dialogs, source-tab changes, background idle/wakeup, and failed dialog initialization do not mix or silently lose selections. - Long selected text requires consent; oversized/unsupported URLs do not launch. - Tab/window preferences and failure fallback work from direct and dialog paths. - Settings/dialogs work in light/dark themes, narrow layouts, and by keyboard. - Run the existing AGENTS.md frame-focus and restricted-page shortcut checks. Update README, changelog, and privacy text for menu modes, presets, URL sharing, translation, and truncation. Remove the unsuccessful temporary model/effort URL-test controls as part of release cleanup. Do not promise that ChatGPT can access every supplied URL or perform a definitive security audit. ## Review outcome The design separates selection text from whole URLs in its length handling, keeps translation opt-in, preserves legacy menu behavior, and leaves Firefox's search provider and shortcut ownership unchanged. The next step after written spec approval is an implementation plan; this document authorizes no additional features beyond the agreed scope.