@@ -6,9 +6,11 @@ import { APP_ROOT } from '../constants';
6
6
import { HtkConfig } from '../config' ;
7
7
import { logError } from '../error-tracking' ;
8
8
9
- import { getAvailableBrowsers , launchBrowser , BrowserInstance } from '../browsers' ;
10
9
import { delay } from '../util/promise' ;
11
10
import { isErrorLike } from '../util/error' ;
11
+ import { isSnap , getSnapConfigPath } from '../util/snap' ;
12
+
13
+ import { launchBrowser , BrowserInstance , getBrowserDetails } from '../browsers' ;
12
14
import { readFile , canAccess , deleteFolder } from '../util/fs' ;
13
15
import { windowsKill , spawnToResult } from '../util/process-management' ;
14
16
import { MessageServer } from '../message-server' ;
@@ -73,23 +75,20 @@ export class FreshFirefox implements Interceptor {
73
75
74
76
constructor ( private config : HtkConfig ) { }
75
77
76
- private readonly firefoxProfilePath = path . join ( this . config . configPath , 'firefox-profile' ) ;
77
-
78
78
isActive ( proxyPort : number | string ) {
79
79
return browsers [ proxyPort ] != null && ! ! browsers [ proxyPort ] . pid ;
80
80
}
81
81
82
82
async isActivable ( ) {
83
- const availableBrowsers = await getAvailableBrowsers ( this . config . configPath ) ;
84
-
85
- const firefoxBrowser = _ . find ( availableBrowsers , { name : 'firefox' } ) ;
83
+ const firefoxBrowser = await getBrowserDetails ( this . config . configPath , 'firefox' ) ;
86
84
87
85
return ! ! firefoxBrowser && // Must have Firefox installed
88
86
parseInt ( firefoxBrowser . version . split ( '.' ) [ 0 ] , 0 ) >= 58 && // Must use cert9.db
89
87
await getCertutilCommand ( ) . then ( ( ) => true ) . catch ( ( ) => false ) // Must have certutil available
90
88
}
91
89
92
90
async startFirefox (
91
+ profilePath : string ,
93
92
initialServer : MessageServer | CertCheckServer ,
94
93
proxyPort ?: number ,
95
94
existingPrefs = { }
@@ -98,7 +97,7 @@ export class FreshFirefox implements Interceptor {
98
97
99
98
const browser = await launchBrowser ( initialUrl , {
100
99
browser : 'firefox' ,
101
- profile : this . firefoxProfilePath ,
100
+ profile : profilePath ,
102
101
proxy : proxyPort ? `127.0.0.1:${ proxyPort } ` : undefined ,
103
102
prefs : _ . assign (
104
103
existingPrefs ,
@@ -184,7 +183,7 @@ export class FreshFirefox implements Interceptor {
184
183
}
185
184
186
185
// Create the profile. We need to run FF to do its setup, then close it & edit more ourselves.
187
- async setupFirefoxProfile ( ) {
186
+ async setupFirefoxProfile ( profilePath : string ) {
188
187
const messageServer = new MessageServer (
189
188
this . config ,
190
189
`HTTP Toolkit is preparing a Firefox profile, please wait...`
@@ -193,15 +192,15 @@ export class FreshFirefox implements Interceptor {
193
192
194
193
let messageShown : Promise < void > | true = messageServer . waitForSuccess ( ) . catch ( logError ) ;
195
194
196
- profileSetupBrowser = await this . startFirefox ( messageServer ) ;
195
+ profileSetupBrowser = await this . startFirefox ( profilePath , messageServer ) ;
197
196
profileSetupBrowser . process . once ( 'close' , ( exitCode ) => {
198
197
console . log ( "Profile setup Firefox closed" ) ;
199
198
messageServer . stop ( ) ;
200
199
profileSetupBrowser = undefined ;
201
200
202
201
if ( messageShown !== true ) {
203
202
logError ( `Firefox profile setup failed with code ${ exitCode } ` ) ;
204
- deleteFolder ( this . firefoxProfilePath ) . catch ( console . warn ) ;
203
+ deleteFolder ( profilePath ) . catch ( console . warn ) ;
205
204
}
206
205
} ) ;
207
206
@@ -222,7 +221,7 @@ export class FreshFirefox implements Interceptor {
222
221
const certUtilResult = await spawnToResult (
223
222
certutil . command , [
224
223
'-A' ,
225
- '-d' , `sql:${ this . firefoxProfilePath } ` ,
224
+ '-d' , `sql:${ profilePath } ` ,
226
225
'-t' , 'C,,' ,
227
226
'-i' , this . config . https . certPath ,
228
227
'-n' , 'HTTP Toolkit'
@@ -240,7 +239,14 @@ export class FreshFirefox implements Interceptor {
240
239
async activate ( proxyPort : number ) {
241
240
if ( this . isActive ( proxyPort ) || ! ! profileSetupBrowser ) return ;
242
241
243
- const firefoxPrefsFile = path . join ( this . firefoxProfilePath , 'prefs.js' ) ;
242
+ const browserDetails = await getBrowserDetails ( this . config . configPath , 'firefox' ) ;
243
+ if ( ! browserDetails ) throw new Error ( 'Firefox could not be detected' ) ;
244
+
245
+ const profilePath = await isSnap ( browserDetails . command )
246
+ ? path . join ( getSnapConfigPath ( 'firefox' ) , 'profile' )
247
+ : path . join ( this . config . configPath , 'firefox-profile' ) ;
248
+
249
+ const firefoxPrefsFile = path . join ( profilePath , 'prefs.js' ) ;
244
250
245
251
let existingPrefs : _ . Dictionary < any > = { } ;
246
252
@@ -250,7 +256,7 @@ export class FreshFirefox implements Interceptor {
250
256
This helps avoid initial Firefox profile setup request noise, and tidies up some awkward UX where
251
257
firefox likes to open extra welcome windows/tabs on first run.
252
258
*/
253
- await this . setupFirefoxProfile ( ) ;
259
+ await this . setupFirefoxProfile ( profilePath ) ;
254
260
}
255
261
256
262
// We need to preserve & reuse any existing preferences, to avoid issues
@@ -272,7 +278,7 @@ export class FreshFirefox implements Interceptor {
272
278
const certCheckServer = new CertCheckServer ( this . config ) ;
273
279
await certCheckServer . start ( "https://amiusing.httptoolkit.tech" ) ;
274
280
275
- const browser = await this . startFirefox ( certCheckServer , proxyPort , existingPrefs ) ;
281
+ const browser = await this . startFirefox ( profilePath , certCheckServer , proxyPort , existingPrefs ) ;
276
282
277
283
let certCheckSuccessful : boolean | undefined ;
278
284
certCheckServer . waitForSuccess ( ) . then ( ( ) => {
@@ -300,7 +306,7 @@ export class FreshFirefox implements Interceptor {
300
306
? "failed"
301
307
: "did not complete"
302
308
} with FF exit code ${ exitCode } `) ;
303
- deleteFolder ( this . firefoxProfilePath ) . catch ( console . warn ) ;
309
+ deleteFolder ( profilePath ) . catch ( console . warn ) ;
304
310
}
305
311
} ) ;
306
312
0 commit comments