22 computeSystemExecutablePath ,
33 Browser ,
44 ChromeReleaseChannel ,
5- launch ,
65} from '@puppeteer/browsers'
76import { exec , spawn } from 'child_process'
87import { app , BrowserWindow } from 'electron'
@@ -13,6 +12,7 @@ import path from 'path'
1312import { promisify } from 'util'
1413
1514import { getCertificateSPKI } from '@/main/proxy'
15+ import { ChromeDevtoolsClient } from '@/utils/cdp/client'
1616
1717import { BrowserServer } from '../../services/browser/server'
1818import { getPlatform } from '../../utils/electron'
@@ -52,6 +52,18 @@ function getExtensionPath() {
5252 return path . join ( process . resourcesPath , 'extension' )
5353}
5454
55+ const FEATURES_TO_DISABLE = [
56+ 'OptimizationGuideModelDownloading' ,
57+ 'OptimizationHintsFetching' ,
58+ 'OptimizationTargetPrediction' ,
59+ 'OptimizationHints' ,
60+ ]
61+
62+ const BROWSER_RECORDING_ARGS = [
63+ '--remote-debugging-pipe' ,
64+ '--enable-unsafe-extension-debugging' ,
65+ ]
66+
5567export const launchBrowser = async (
5668 browserWindow : BrowserWindow ,
5769 browserServer : BrowserServer ,
@@ -64,21 +76,9 @@ export const launchBrowser = async (
6476 console . log ( userDataDir )
6577 const certificateSPKI = await getCertificateSPKI ( )
6678
67- const optimizationsToDisable = [
68- 'OptimizationGuideModelDownloading' ,
69- 'OptimizationHintsFetching' ,
70- 'OptimizationTargetPrediction' ,
71- 'OptimizationHints' ,
72- ]
73- const disableChromeOptimizations = `--disable-features=${ optimizationsToDisable . join ( ',' ) } `
74-
7579 const extensionPath = getExtensionPath ( )
7680 console . info ( `extension path: ${ extensionPath } ` )
7781
78- if ( capture . browser ) {
79- browserServer . start ( browserWindow )
80- }
81-
8282 const handleBrowserClose = ( ) : Promise < void > => {
8383 browserServer . stop ( )
8484
@@ -95,9 +95,7 @@ export const launchBrowser = async (
9595 browserWindow . webContents . send ( BrowserHandler . Failed )
9696 }
9797
98- const browserRecordingArgs = capture . browser
99- ? [ `--load-extension=${ extensionPath } ` ]
100- : [ ]
98+ const browserRecordingArgs = capture . browser ? BROWSER_RECORDING_ARGS : [ ]
10199
102100 const args = [
103101 '--new' ,
@@ -112,28 +110,36 @@ export const launchBrowser = async (
112110 '--disable-search-engine-choice-screen' ,
113111 `--proxy-server=http://localhost:${ k6StudioState . appSettings . proxy . port } ` ,
114112 `--ignore-certificate-errors-spki-list=${ certificateSPKI } ` ,
113+ `--disable-features=${ FEATURES_TO_DISABLE . join ( ',' ) } ` ,
115114 ...browserRecordingArgs ,
116- disableChromeOptimizations ,
117115 url ?. trim ( ) || 'about:blank' ,
118116 ]
119117
120- // if we are on linux we spawn the browser directly and attach the on exit callback
121- if ( getPlatform ( ) === 'linux' ) {
122- const browserProc = spawn ( path , args )
118+ const process = spawn ( path , args , {
119+ stdio : [ 'ignore' , 'ignore' , 'ignore' , 'pipe' , 'pipe' ] ,
120+ } )
123121
124- browserProc . on ( 'error' , handleBrowserLaunchError )
125- browserProc . once ( 'exit' , handleBrowserClose )
126- return browserProc
122+ if ( capture . browser ) {
123+ browserServer . start ( browserWindow )
124+
125+ const client = ChromeDevtoolsClient . fromChildProcess ( process )
126+
127+ process . on ( 'spawn' , async ( ) => {
128+ const response = await client . call ( {
129+ method : 'Extensions.loadUnpacked' ,
130+ params : {
131+ path : extensionPath ,
132+ } ,
133+ } )
134+
135+ console . log ( `k6 Studio extension loaded` , response )
136+ } )
127137 }
128138
129- // macOS & windows
130- const browserProc = launch ( {
131- executablePath : path ,
132- args : args ,
133- onExit : handleBrowserClose ,
134- } )
135- browserProc . nodeProcess . on ( 'error' , handleBrowserLaunchError )
136- return browserProc
139+ process . on ( 'error' , handleBrowserLaunchError )
140+ process . once ( 'exit' , handleBrowserClose )
141+
142+ return process
137143}
138144
139145function getChromePath ( ) {
0 commit comments