@@ -20,7 +20,6 @@ import { Interceptor } from '.';
2020const FIREFOX_PREF_REGEX = / \w + _ p r e f \( " ( [ ^ " ] + ) " , ( .* ) \) ; /
2121
2222let profileSetupBrowser : BrowserInstance | undefined ;
23- let browsers : _ . Dictionary < BrowserInstance > = { } ;
2423
2524export const NSS_DIR = path . join ( APP_ROOT , 'nss' ) ;
2625
@@ -69,18 +68,26 @@ const getCertutilCommand = _.memoize(async () => {
6968 }
7069} ) ;
7170
72- export class FreshFirefox implements Interceptor {
73- id = 'fresh-firefox' ;
74- version = '1.1.0' ;
71+ abstract class Firefox implements Interceptor {
72+ readonly abstract id : string ;
73+ readonly abstract version : string ;
74+
75+ protected constructor (
76+ private config : HtkConfig ,
77+ private variantName : string ,
78+ private pathName : string = variantName + '-profile' ,
79+ ) { }
80+
81+ private readonly activeBrowsers : _ . Dictionary < BrowserInstance > = { } ;
7582
76- constructor ( private config : HtkConfig ) { }
7783
7884 isActive ( proxyPort : number | string ) {
79- return browsers [ proxyPort ] != null && ! ! browsers [ proxyPort ] . pid ;
85+ const browser = this . activeBrowsers [ proxyPort ] ;
86+ return ! ! browser && ! ! browser . pid ;
8087 }
8188
8289 async isActivable ( ) {
83- const firefoxBrowser = await getBrowserDetails ( this . config . configPath , 'firefox' ) ;
90+ const firefoxBrowser = await getBrowserDetails ( this . config . configPath , this . variantName ) ;
8491
8592 return ! ! firefoxBrowser && // Must have Firefox installed
8693 parseInt ( firefoxBrowser . version . split ( '.' ) [ 0 ] , 0 ) >= 58 && // Must use cert9.db
@@ -96,7 +103,7 @@ export class FreshFirefox implements Interceptor {
96103 const initialUrl = initialServer . url ;
97104
98105 const browser = await launchBrowser ( initialUrl , {
99- browser : 'firefox' ,
106+ browser : this . variantName ,
100107 profile : profilePath ,
101108 proxy : proxyPort ? `127.0.0.1:${ proxyPort } ` : undefined ,
102109 prefs : _ . assign (
@@ -239,18 +246,18 @@ export class FreshFirefox implements Interceptor {
239246 async activate ( proxyPort : number ) {
240247 if ( this . isActive ( proxyPort ) || ! ! profileSetupBrowser ) return ;
241248
242- const browserDetails = await getBrowserDetails ( this . config . configPath , 'firefox' ) ;
249+ const browserDetails = await getBrowserDetails ( this . config . configPath , this . variantName ) ;
243250 if ( ! browserDetails ) throw new Error ( 'Firefox could not be detected' ) ;
244251
245252 const profilePath = await isSnap ( browserDetails . command )
246- ? path . join ( await getSnapConfigPath ( 'firefox' ) , 'profile' )
247- : path . join ( this . config . configPath , 'firefox-profile' ) ;
253+ ? path . join ( await getSnapConfigPath ( this . variantName ) , 'profile' )
254+ : path . join ( this . config . configPath , this . pathName ) ;
248255
249256 const firefoxPrefsFile = path . join ( profilePath , 'prefs.js' ) ;
250257
251258 let existingPrefs : _ . Dictionary < any > = { } ;
252259
253- if ( await canAccess ( firefoxPrefsFile ) === false ) {
260+ if ( ! await canAccess ( firefoxPrefsFile ) ) {
254261 /*
255262 First time, we do a separate pre-usage startup & stop, without the proxy, for certificate setup.
256263 This helps avoid initial Firefox profile setup request noise, and tidies up some awkward UX where
@@ -288,10 +295,10 @@ export class FreshFirefox implements Interceptor {
288295 logError ( e ) ;
289296 } ) ;
290297
291- browsers [ proxyPort ] = browser ;
298+ this . activeBrowsers [ proxyPort ] = browser ;
292299 browser . process . once ( 'close' , async ( exitCode ) => {
293300 console . log ( 'Firefox closed' ) ;
294- delete browsers [ proxyPort ] ;
301+ delete this . activeBrowsers [ proxyPort ] ;
295302
296303 // It seems maybe this can happen when firefox is just updated - it starts and
297304 // closes immediately, but loses some settings along the way. In that case, the 2nd
@@ -316,7 +323,7 @@ export class FreshFirefox implements Interceptor {
316323
317324 async deactivate ( proxyPort : number | string ) {
318325 if ( this . isActive ( proxyPort ) ) {
319- const browser = browsers [ proxyPort ] ;
326+ const browser = this . activeBrowsers [ proxyPort ] ;
320327 const closePromise = new Promise ( ( resolve ) => browser . process . once ( 'close' , resolve ) ) ;
321328 browser . stop ( ) ;
322329 await closePromise ;
@@ -325,11 +332,41 @@ export class FreshFirefox implements Interceptor {
325332
326333 async deactivateAll ( ) : Promise < void > {
327334 await Promise . all (
328- Object . keys ( browsers ) . map ( ( proxyPort ) => this . deactivate ( proxyPort ) )
335+ Object . keys ( this . activeBrowsers ) . map ( ( proxyPort ) => this . deactivate ( proxyPort ) )
329336 ) ;
330337 if ( profileSetupBrowser ) {
331338 profileSetupBrowser . stop ( ) ;
332339 return new Promise ( ( resolve ) => profileSetupBrowser ! . process . once ( 'close' , resolve ) ) ;
333340 }
334341 }
342+ } ;
343+
344+ export class FreshFirefox extends Firefox {
345+
346+ id = 'fresh-firefox' ;
347+ version = '1.2.0' ;
348+
349+ constructor ( config : HtkConfig ) {
350+ super ( config , 'firefox' ) ;
351+ }
352+ } ;
353+
354+ export class FreshFirefoxDeveloper extends Firefox {
355+
356+ id = 'fresh-firefox-dev' ;
357+ version = '1.2.0' ;
358+
359+ constructor ( config : HtkConfig ) {
360+ super ( config , 'firefox-developer' ) ;
361+ }
362+ } ;
363+
364+ export class FreshFirefoxNightly extends Firefox {
365+
366+ id = 'fresh-firefox-nightly' ;
367+ version = '1.2.0' ;
368+
369+ constructor ( config : HtkConfig ) {
370+ super ( config , 'firefox-nightly' ) ;
371+ }
335372} ;
0 commit comments