33 * Licensed under the MIT License. See License.txt in the project root for license information.
44 *--------------------------------------------------------------------------------------------*/
55
6- import { BrowserType , IElementData , INativeBrowserElementsService } from '../common/browserElements.js' ;
6+ import { IElementData , INativeBrowserElementsService , IBrowserTargetLocator } from '../common/browserElements.js' ;
77import { CancellationToken } from '../../../base/common/cancellation.js' ;
88import { IRectangle } from '../../window/common/window.js' ;
99import { BrowserWindow , webContents } from 'electron' ;
@@ -14,6 +14,7 @@ import { IWindowsMainService } from '../../windows/electron-main/windows.js';
1414import { createDecorator } from '../../instantiation/common/instantiation.js' ;
1515import { Disposable } from '../../../base/common/lifecycle.js' ;
1616import { AddFirstParameterToFunctions } from '../../../base/common/types.js' ;
17+ import { IBrowserViewMainService } from '../../browserView/electron-main/browserViewMainService.js' ;
1718
1819export const INativeBrowserElementsMainService = createDecorator < INativeBrowserElementsMainService > ( 'browserElementsMainService' ) ;
1920export interface INativeBrowserElementsMainService extends AddFirstParameterToFunctions < INativeBrowserElementsService , Promise < unknown > /* only methods, not events */ , number | undefined /* window ID */ > { }
@@ -27,89 +28,78 @@ interface NodeDataResponse {
2728export class NativeBrowserElementsMainService extends Disposable implements INativeBrowserElementsMainService {
2829 _serviceBrand : undefined ;
2930
30- currentLocalAddress : string | undefined ;
31-
3231 constructor (
3332 @IWindowsMainService private readonly windowsMainService : IWindowsMainService ,
3433 @IAuxiliaryWindowsMainService private readonly auxiliaryWindowsMainService : IAuxiliaryWindowsMainService ,
35-
34+ @ IBrowserViewMainService private readonly browserViewMainService : IBrowserViewMainService
3635 ) {
3736 super ( ) ;
3837 }
3938
4039 get windowId ( ) : never { throw new Error ( 'Not implemented in electron-main' ) ; }
4140
42- async findWebviewTarget ( debuggers : Electron . Debugger , windowId : number , browserType : BrowserType ) : Promise < string | undefined > {
41+ /**
42+ * Find the webview target that matches the given locator.
43+ * Checks either webviewId or browserViewId depending on what's provided.
44+ */
45+ async findWebviewTarget ( debuggers : Electron . Debugger , locator : IBrowserTargetLocator ) : Promise < string | undefined > {
4346 const { targetInfos } = await debuggers . sendCommand ( 'Target.getTargets' ) ;
44- let target : typeof targetInfos [ number ] | undefined = undefined ;
45- const matchingTarget = targetInfos . find ( ( targetInfo : { url : string } ) => {
46- try {
47- const url = new URL ( targetInfo . url ) ;
48- if ( browserType === BrowserType . LiveServer ) {
49- return url . searchParams . get ( 'id' ) && url . searchParams . get ( 'extensionId' ) === 'ms-vscode.live-server' ;
50- } else if ( browserType === BrowserType . SimpleBrowser ) {
51- return url . searchParams . get ( 'parentId' ) === windowId . toString ( ) && url . searchParams . get ( 'extensionId' ) === 'vscode.simple-browser' ;
47+
48+ if ( locator . webviewId ) {
49+ let extensionId = '' ;
50+ for ( const targetInfo of targetInfos ) {
51+ try {
52+ const url = new URL ( targetInfo . url ) ;
53+ if ( url . searchParams . get ( 'id' ) === locator . webviewId ) {
54+ extensionId = url . searchParams . get ( 'extensionId' ) || '' ;
55+ break ;
56+ }
57+ } catch ( err ) {
58+ // ignore
5259 }
53- return false ;
54- } catch ( err ) {
55- return false ;
5660 }
57- } ) ;
58-
59- // search for webview via search parameters
60- if ( matchingTarget ) {
61- let resultId : string | undefined ;
62- let url : URL | undefined ;
63- try {
64- url = new URL ( matchingTarget . url ) ;
65- resultId = url . searchParams . get ( 'id' ) ! ;
66- } catch ( e ) {
61+ if ( ! extensionId ) {
6762 return undefined ;
6863 }
6964
70- target = targetInfos . find ( ( targetInfo : { url : string } ) => {
65+ // search for webview via search parameters
66+ const target = targetInfos . find ( ( targetInfo : { url : string } ) => {
7167 try {
7268 const url = new URL ( targetInfo . url ) ;
73- const isLiveServer = browserType === BrowserType . LiveServer && url . searchParams . get ( 'serverWindowId' ) === resultId ;
74- const isSimpleBrowser = browserType === BrowserType . SimpleBrowser && url . searchParams . get ( 'id' ) === resultId && url . searchParams . has ( 'vscodeBrowserReqId' ) ;
69+ const isLiveServer = extensionId === 'ms-vscode.live-server' && url . searchParams . get ( 'serverWindowId' ) === locator . webviewId ;
70+ const isSimpleBrowser = extensionId === 'vscode.simple-browser' && url . searchParams . get ( 'id' ) === locator . webviewId && url . searchParams . has ( 'vscodeBrowserReqId' ) ;
7571 if ( isLiveServer || isSimpleBrowser ) {
76- this . currentLocalAddress = url . origin ;
7772 return true ;
7873 }
7974 return false ;
8075 } catch ( e ) {
8176 return false ;
8277 }
8378 } ) ;
84-
85- if ( target ) {
86- return target . targetId ;
87- }
79+ return target ?. targetId ;
8880 }
8981
90- // fallback: search for webview without parameters based on current origin
91- target = targetInfos . find ( ( targetInfo : { url : string } ) => {
92- try {
93- const url = new URL ( targetInfo . url ) ;
94- return ( this . currentLocalAddress === url . origin ) ;
95- } catch ( e ) {
96- return false ;
97- }
98- } ) ;
82+ if ( locator . browserViewId ) {
83+ const webContentsInstance = this . browserViewMainService . tryGetBrowserView ( locator . browserViewId ) ?. webContents ;
84+ const target = targetInfos . find ( ( targetInfo : { targetId : string ; type : string } ) => {
85+ if ( targetInfo . type !== 'page' ) {
86+ return false ;
87+ }
9988
100- if ( ! target ) {
101- return undefined ;
89+ return webContents . fromDevToolsTargetId ( targetInfo . targetId ) === webContentsInstance ;
90+ } ) ;
91+ return target ?. targetId ;
10292 }
10393
104- return target . targetId ;
94+ return undefined ;
10595 }
10696
107- async waitForWebviewTargets ( debuggers : Electron . Debugger , windowId : number , browserType : BrowserType ) : Promise < string | undefined > {
97+ async waitForWebviewTargets ( debuggers : Electron . Debugger , locator : IBrowserTargetLocator ) : Promise < string | undefined > {
10898 const start = Date . now ( ) ;
10999 const timeout = 10000 ;
110100
111101 while ( Date . now ( ) - start < timeout ) {
112- const targetId = await this . findWebviewTarget ( debuggers , windowId , browserType ) ;
102+ const targetId = await this . findWebviewTarget ( debuggers , locator ) ;
113103 if ( targetId ) {
114104 return targetId ;
115105 }
@@ -122,7 +112,7 @@ export class NativeBrowserElementsMainService extends Disposable implements INat
122112 return undefined ;
123113 }
124114
125- async startDebugSession ( windowId : number | undefined , token : CancellationToken , browserType : BrowserType , cancelAndDetachId ?: number ) : Promise < void > {
115+ async startDebugSession ( windowId : number | undefined , token : CancellationToken , locator : IBrowserTargetLocator , cancelAndDetachId ?: number ) : Promise < void > {
126116 const window = this . windowById ( windowId ) ;
127117 if ( ! window ?. win ) {
128118 return undefined ;
@@ -142,7 +132,7 @@ export class NativeBrowserElementsMainService extends Disposable implements INat
142132 }
143133
144134 try {
145- const matchingTargetId = await this . waitForWebviewTargets ( debuggers , windowId ! , browserType ) ;
135+ const matchingTargetId = await this . waitForWebviewTargets ( debuggers , locator ) ;
146136 if ( ! matchingTargetId ) {
147137 if ( debuggers . isAttached ( ) ) {
148138 debuggers . detach ( ) ;
@@ -187,7 +177,7 @@ export class NativeBrowserElementsMainService extends Disposable implements INat
187177 }
188178 }
189179
190- async getElementData ( windowId : number | undefined , rect : IRectangle , token : CancellationToken , browserType : BrowserType , cancellationId ?: number ) : Promise < IElementData | undefined > {
180+ async getElementData ( windowId : number | undefined , rect : IRectangle , token : CancellationToken , locator : IBrowserTargetLocator , cancellationId ?: number ) : Promise < IElementData | undefined > {
191181 const window = this . windowById ( windowId ) ;
192182 if ( ! window ?. win ) {
193183 return undefined ;
@@ -208,7 +198,7 @@ export class NativeBrowserElementsMainService extends Disposable implements INat
208198
209199 let targetSessionId : string | undefined = undefined ;
210200 try {
211- const targetId = await this . findWebviewTarget ( debuggers , windowId ! , browserType ) ;
201+ const targetId = await this . findWebviewTarget ( debuggers , locator ) ;
212202 const { sessionId } = await debuggers . sendCommand ( 'Target.attachToTarget' , {
213203 targetId : targetId ,
214204 flatten : true ,
@@ -373,7 +363,7 @@ export class NativeBrowserElementsMainService extends Disposable implements INat
373363 const content = model . content ;
374364 const margin = model . margin ;
375365 const x = Math . min ( margin [ 0 ] , content [ 0 ] ) ;
376- const y = Math . min ( margin [ 1 ] , content [ 1 ] ) + 32.4 ; // 32.4 is height of the title bar
366+ const y = Math . min ( margin [ 1 ] , content [ 1 ] ) ;
377367 const width = Math . max ( margin [ 2 ] - margin [ 0 ] , content [ 2 ] - content [ 0 ] ) ;
378368 const height = Math . max ( margin [ 5 ] - margin [ 1 ] , content [ 5 ] - content [ 1 ] ) ;
379369
@@ -416,7 +406,7 @@ export class NativeBrowserElementsMainService extends Disposable implements INat
416406 } ) ;
417407 }
418408
419- formatMatchedStyles ( matched : { inlineStyle ?: { cssProperties ?: Array < { name : string ; value : string } > } ; matchedCSSRules ?: Array < { rule : { selectorList : { selectors : Array < { text : string } > } ; origin : string ; style : { cssProperties : Array < { name : string ; value : string } > } } } > ; inherited ?: Array < { matchedCSSRules ?: Array < { rule : { selectorList : { selectors : Array < { text : string } > } ; origin : string ; style : { cssProperties : Array < { name : string ; value : string } > } } } > } > } ) : string {
409+ formatMatchedStyles ( matched : { inlineStyle ?: { cssProperties ?: Array < { name : string ; value : string } > } ; matchedCSSRules ?: Array < { rule : { selectorList : { selectors : Array < { text : string } > } ; origin : string ; style : { cssProperties : Array < { name : string ; value : string } > } } } > ; inherited ?: Array < { inlineStyle ?: { cssText : string } ; matchedCSSRules ?: Array < { rule : { selectorList : { selectors : Array < { text : string } > } ; origin : string ; style : { cssProperties : Array < { name : string ; value : string } > } } } > } > } ) : string {
420410 const lines : string [ ] = [ ] ;
421411
422412 // inline
@@ -451,6 +441,14 @@ export class NativeBrowserElementsMainService extends Disposable implements INat
451441 if ( matched . inherited ?. length ) {
452442 let level = 1 ;
453443 for ( const inherited of matched . inherited ) {
444+ const inline = inherited . inlineStyle ;
445+ if ( inline ) {
446+ lines . push ( `/* Inherited from ancestor level ${ level } (inline) */` ) ;
447+ lines . push ( 'element {' ) ;
448+ lines . push ( inline . cssText ) ;
449+ lines . push ( '}\n' ) ;
450+ }
451+
454452 const rules = inherited . matchedCSSRules || [ ] ;
455453 for ( const ruleEntry of rules ) {
456454 const rule = ruleEntry . rule ;
0 commit comments