3131// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
3232/* eslint-disable @typescript-eslint/naming-convention */
3333
34+ import { type Chrome } from '../../../extension-api/ExtensionAPI.js' ; // eslint-disable-line rulesdir/es_modules_import
3435import * as Common from '../../core/common/common.js' ;
3536import * as Host from '../../core/host/host.js' ;
3637import * as i18n from '../../core/i18n/i18n.js' ;
3738import * as Platform from '../../core/platform/platform.js' ;
3839import * as _ProtocolClient from '../../core/protocol_client/protocol_client.js' ; // eslint-disable-line @typescript-eslint/no-unused-vars
3940import * as Root from '../../core/root/root.js' ;
4041import * as SDK from '../../core/sdk/sdk.js' ;
42+ import type * as Protocol from '../../generated/protocol.js' ;
4143import * as Logs from '../../models/logs/logs.js' ;
4244import * as Components from '../../ui/legacy/components/utils/utils.js' ;
4345import * as UI from '../../ui/legacy/legacy.js' ;
@@ -46,15 +48,13 @@ import * as Bindings from '../bindings/bindings.js';
4648import * as HAR from '../har/har.js' ;
4749import type * as TextUtils from '../text_utils/text_utils.js' ;
4850import * as Workspace from '../workspace/workspace.js' ;
49- import type * as Protocol from '../../generated/protocol.js' ;
5051
52+ import { PrivateAPI } from './ExtensionAPI.js' ;
5153import { ExtensionButton , ExtensionPanel , ExtensionSidebarPane } from './ExtensionPanel.js' ;
52-
54+ import { HostUrlPattern } from './HostUrlPattern.js' ;
5355import { LanguageExtensionEndpoint } from './LanguageExtensionEndpoint.js' ;
5456import { RecorderExtensionEndpoint } from './RecorderExtensionEndpoint.js' ;
55- import { PrivateAPI } from './ExtensionAPI.js' ;
5657import { RecorderPluginManager } from './RecorderPluginManager.js' ;
57- import { type Chrome } from '../../../extension-api/ExtensionAPI.js' ; // eslint-disable-line rulesdir/es_modules_import
5858
5959const extensionOrigins : WeakMap < MessagePort , Platform . DevToolsPath . UrlString > = new WeakMap ( ) ;
6060
@@ -68,6 +68,32 @@ const kAllowedOrigins = [].map(url => (new URL(url)).origin);
6868
6969let extensionServerInstance : ExtensionServer | null ;
7070
71+ export class HostsPolicy {
72+ static create ( policy ?: Host . InspectorFrontendHostAPI . ExtensionHostsPolicy ) : HostsPolicy | null {
73+ const runtimeAllowedHosts = [ ] ;
74+ const runtimeBlockedHosts = [ ] ;
75+ if ( policy ) {
76+ for ( const pattern of policy . runtimeAllowedHosts ) {
77+ const parsedPattern = HostUrlPattern . parse ( pattern ) ;
78+ if ( ! parsedPattern ) {
79+ return null ;
80+ }
81+ runtimeAllowedHosts . push ( parsedPattern ) ;
82+ }
83+ for ( const pattern of policy . runtimeBlockedHosts ) {
84+ const parsedPattern = HostUrlPattern . parse ( pattern ) ;
85+ if ( ! parsedPattern ) {
86+ return null ;
87+ }
88+ runtimeBlockedHosts . push ( parsedPattern ) ;
89+ }
90+ }
91+ return new HostsPolicy ( runtimeAllowedHosts , runtimeBlockedHosts ) ;
92+ }
93+ private constructor ( readonly runtimeAllowedHosts : HostUrlPattern [ ] , readonly runtimeBlockedHosts : HostUrlPattern [ ] ) {
94+ }
95+ }
96+
7197export class ExtensionServer extends Common . ObjectWrapper . ObjectWrapper < EventTypes > {
7298 private readonly clientObjects : Map < string , unknown > ;
7399 private readonly handlers :
@@ -81,6 +107,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
81107 private lastRequestId : number ;
82108 private registeredExtensions : Map < string , {
83109 name : string ,
110+ hostsPolicy : HostsPolicy ,
84111 } > ;
85112 private status : ExtensionStatus ;
86113 private readonly sidebarPanesInternal : ExtensionSidebarPane [ ] ;
@@ -363,7 +390,9 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
363390 }
364391 const message = { command : 'notify-' + type , arguments : Array . prototype . slice . call ( arguments , 1 ) } ;
365392 for ( const subscriber of subscribers ) {
366- subscriber . postMessage ( message ) ;
393+ if ( this . extensionEnabled ( subscriber ) ) {
394+ subscriber . postMessage ( message ) ;
395+ }
367396 }
368397 }
369398
@@ -953,7 +982,11 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
953982 addExtensionForTest ( extensionInfo : Host . InspectorFrontendHostAPI . ExtensionDescriptor , origin : string ) : boolean
954983 | undefined {
955984 const name = extensionInfo . name || `Extension ${ origin } ` ;
956- this . registeredExtensions . set ( origin , { name} ) ;
985+ const hostsPolicy = HostsPolicy . create ( extensionInfo . hostsPolicy ) ;
986+ if ( ! hostsPolicy ) {
987+ return false ;
988+ }
989+ this . registeredExtensions . set ( origin , { name, hostsPolicy} ) ;
957990 return true ;
958991 }
959992
@@ -967,6 +1000,10 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
9671000 if ( ! this . extensionsEnabled ) {
9681001 return ;
9691002 }
1003+ const hostsPolicy = HostsPolicy . create ( extensionInfo . hostsPolicy ) ;
1004+ if ( ! hostsPolicy ) {
1005+ return ;
1006+ }
9701007 try {
9711008 const startPageURL = new URL ( ( startPage as string ) ) ;
9721009 const extensionOrigin = startPageURL . origin ;
@@ -979,7 +1016,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
9791016 Host . InspectorFrontendHost . InspectorFrontendHostInstance . setInjectedScriptForOrigin (
9801017 extensionOrigin , injectedAPI ) ;
9811018 const name = extensionInfo . name || `Extension ${ extensionOrigin } ` ;
982- this . registeredExtensions . set ( extensionOrigin , { name} ) ;
1019+ this . registeredExtensions . set ( extensionOrigin , { name, hostsPolicy } ) ;
9831020 }
9841021
9851022 const iframe = document . createElement ( 'iframe' ) ;
@@ -1012,15 +1049,42 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
10121049 }
10131050 } ;
10141051
1052+ private extensionEnabled ( port : MessagePort ) : boolean {
1053+ if ( ! this . extensionsEnabled ) {
1054+ return false ;
1055+ }
1056+ const origin = extensionOrigins . get ( port ) ;
1057+ if ( ! origin ) {
1058+ return false ;
1059+ }
1060+ const extension = this . registeredExtensions . get ( origin ) ;
1061+ if ( ! extension ) {
1062+ return false ;
1063+ }
1064+
1065+ const inspectedURL = SDK . TargetManager . TargetManager . instance ( ) . primaryPageTarget ( ) ?. inspectedURL ( ) ;
1066+ if ( ! inspectedURL ) {
1067+ // If there aren't any blocked hosts retain the old behavior and don't worry about the inspectedURL
1068+ return extension . hostsPolicy . runtimeBlockedHosts . length === 0 ;
1069+ }
1070+ if ( extension . hostsPolicy . runtimeBlockedHosts . some ( pattern => pattern . matchesUrl ( inspectedURL ) ) &&
1071+ ! extension . hostsPolicy . runtimeAllowedHosts . some ( pattern => pattern . matchesUrl ( inspectedURL ) ) ) {
1072+ return false ;
1073+ }
1074+
1075+ return true ;
1076+ }
1077+
10151078 private async onmessage ( event : MessageEvent ) : Promise < void > {
10161079 const message = event . data ;
10171080 let result ;
10181081
1082+ const port = event . currentTarget as MessagePort ;
10191083 const handler = this . handlers . get ( message . command ) ;
10201084
10211085 if ( ! handler ) {
10221086 result = this . status . E_NOTSUPPORTED ( message . command ) ;
1023- } else if ( ! this . extensionsEnabled ) {
1087+ } else if ( ! this . extensionEnabled ( port ) ) {
10241088 result = this . status . E_FAILED ( 'Permission denied' ) ;
10251089 } else {
10261090 result = await handler ( message , event . target as MessagePort ) ;
@@ -1217,6 +1281,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
12171281 [ ] ) . includes ( parsedURL . origin ) ) {
12181282 return false ;
12191283 }
1284+
12201285 return true ;
12211286 }
12221287
0 commit comments