@@ -11,10 +11,59 @@ ChromeUtils.defineESModuleGetters(lazy, {
1111 PageThumbs : "resource://gre/modules/PageThumbs.sys.mjs" ,
1212 PageThumbsStorage : "resource://gre/modules/PageThumbs.sys.mjs" ,
1313 getPlacesSemanticHistoryManager : "resource://gre/modules/PlacesSemanticHistoryManager.sys.mjs" ,
14- SecurityOrchestrator :
15- "chrome://global/content/ml/security/SecurityOrchestrator.sys.mjs" ,
1614} ) ;
1715
16+ /**
17+ * Module-level security orchestrator instance.
18+ * Set by SmartWindowPage after initialization.
19+ *
20+ * @type {import("chrome://global/content/ml/security/SecurityOrchestrator.sys.mjs").SecurityOrchestrator|null }
21+ */
22+ let securityOrchestrator = null ;
23+
24+ /**
25+ * Sets the security orchestrator instance for this window's utils module.
26+ * Called by SmartWindowPage after creating the orchestrator.
27+ *
28+ * @param {import("chrome://global/content/ml/security/SecurityOrchestrator.sys.mjs").SecurityOrchestrator|null } orchestrator
29+ */
30+ export function setSecurityOrchestrator ( orchestrator ) {
31+ securityOrchestrator = orchestrator ;
32+ }
33+
34+ /**
35+ * Seeds a URL into the session ledger for the current tab.
36+ * Call this when a user explicitly @mentions a tab/URL.
37+ * This grants the AI permission to access the URL's content.
38+ *
39+ * @param {string } url - The URL to seed
40+ */
41+ export function seedMentionedUrl ( url ) {
42+ if ( ! securityOrchestrator ) {
43+ console . log ( "[Security] No orchestrator - skipping mention seeding" ) ;
44+ return ;
45+ }
46+
47+ const sessionLedger = securityOrchestrator . getSessionLedger ( ) ;
48+ if ( ! sessionLedger ) {
49+ console . log ( "[Security] No session ledger - skipping mention seeding" ) ;
50+ return ;
51+ }
52+
53+ const win = lazy . BrowserWindowTracker . getTopWindow ( ) ;
54+ const gBrowser = win . gBrowser ;
55+ const tabId = gBrowser . selectedTab . linkedPanel ;
56+
57+ const tabLedger = sessionLedger . forTab ( tabId ) ;
58+ const added = tabLedger . add ( url ) ;
59+
60+ if ( added ) {
61+ console . log ( `[Security] Seeded @mentioned URL: ${ url } for tab ${ tabId } ` ) ;
62+ } else {
63+ console . warn ( `[Security] Failed to seed @mentioned URL: ${ url } for tab ${ tabId } ` ) ;
64+ }
65+ }
66+
1867import { createEngine } from "chrome://global/content/ml/EngineProcess.sys.mjs" ;
1968import { SmartAssistEngine } from "moz-src:///browser/components/genai/SmartAssistEngine.sys.mjs" ;
2069import { deleteInsight , findRelatedInsight , generateInsightsFromDirectChat } from "chrome://browser/content/smartwindow/insights.mjs" ;
@@ -598,7 +647,7 @@ async function checkToolSecurity(toolName, toolParams, requestId) {
598647 await browser . browsingContext . currentWindowContext . getActor (
599648 "SmartWindowMeta"
600649 ) ;
601- const sessionLedger = lazy . SecurityOrchestrator . getSessionLedger ( ) ;
650+ const sessionLedger = securityOrchestrator ? .getSessionLedger ( ) ;
602651
603652 if ( ! sessionLedger ) {
604653 console . log (
@@ -633,7 +682,7 @@ async function checkToolSecurity(toolName, toolParams, requestId) {
633682 tabId = gBrowser . selectedTab . linkedPanel ;
634683 }
635684
636- const decision = await lazy . SecurityOrchestrator . evaluate ( {
685+ const decision = await securityOrchestrator . evaluate ( {
637686 phase : "tool.execution" ,
638687 action : {
639688 type : "tool.call" ,
@@ -955,12 +1004,12 @@ export async function* fetchWithHistory(messages, allowedUrls) {
9551004 error : securityCheck . reason || "Security policy denied this action" ,
9561005 } ;
9571006 } else {
958- // Populate allowedUrls from current tab's ledger for headless extraction
1007+ // Merge session ledger URLs with any pre-existing allowedUrls for headless extraction.
9591008 // This allows fetching URLs that are part of the current page's metadata
960- // Such as (canonical URLs, related links, etc.) even if they're not in open tabs
961- let allowedUrls = new Set ( ) ;
1009+ // (canonical URLs, related links, etc.) even if they're not in open tabs.
1010+ let mergedAllowedUrls = new Set ( allowedUrls || [ ] ) ;
9621011 try {
963- const sessionLedger = lazy . SecurityOrchestrator . getSessionLedger ( ) ;
1012+ const sessionLedger = securityOrchestrator ? .getSessionLedger ( ) ;
9641013
9651014 if ( sessionLedger ) {
9661015 // Get current tab ID from tool params or browser
@@ -985,27 +1034,28 @@ export async function* fetchWithHistory(messages, allowedUrls) {
9851034 if ( currentTabId ) {
9861035 const tabLedger = sessionLedger . forTab ( currentTabId ) ;
9871036 if ( tabLedger ) {
988- allowedUrls = new Set ( tabLedger . getAll ( ) ) ;
989- console . log (
990- `[Security] Allowing headless extraction for ${ allowedUrls . size } URLs from current tab ${ currentTabId } `
1037+ for ( const url of tabLedger . getAll ( ) ) {
1038+ mergedAllowedUrls . add ( url ) ;
1039+ }
1040+ console . warn (
1041+ `[Security] Allowing headless extraction for ${ mergedAllowedUrls . size } URLs from current tab ${ currentTabId } `
9911042 ) ;
9921043 }
9931044 }
9941045 }
9951046 } catch ( error ) {
9961047 console . warn (
997- "[Security] Could not populate allowedUrls for headless extraction:" ,
1048+ "[Security] Could not populate mergedAllowedUrls for headless extraction:" ,
9981049 error
9991050 ) ;
1000- allowedUrls = new Set ( ) ;
10011051 }
10021052
10031053 switch ( toolName ) {
10041054 case SEARCH_OPEN_TABS :
10051055 result = search_open_tabs ( toolParams ) ;
10061056 break ;
10071057 case GET_PAGE_CONTENT :
1008- result = await get_page_content ( toolParams , allowedUrls ) ;
1058+ result = await get_page_content ( toolParams , mergedAllowedUrls ) ;
10091059 break ;
10101060 case SEARCH_HISTORY :
10111061 result = await searchBrowserHistory ( toolParams ) ;
0 commit comments