Skip to content

Commit d35b182

Browse files
xKiianpimterry
andauthored
Add firefox developer support (#118)
* added firefox developer support * firefox nightly support * Ship FF variant support as their v1.2.0 release --------- Co-authored-by: Tim Perry <[email protected]>
1 parent 1f345cb commit d35b182

File tree

3 files changed

+59
-18
lines changed

3 files changed

+59
-18
lines changed

src/interceptors/fresh-firefox.ts

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import { Interceptor } from '.';
2020
const FIREFOX_PREF_REGEX = /\w+_pref\("([^"]+)", (.*)\);/
2121

2222
let profileSetupBrowser: BrowserInstance | undefined;
23-
let browsers: _.Dictionary<BrowserInstance> = {};
2423

2524
export 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
};

src/interceptors/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { HtkConfig } from '../config';
44
import { addShutdownHandler } from '../shutdown';
55
import { ErrorLike } from '../util/error';
66

7-
import { FreshFirefox } from './fresh-firefox';
7+
import { FreshFirefox, FreshFirefoxDeveloper, FreshFirefoxNightly } from './fresh-firefox';
88
import {
99
FreshChrome,
1010
ExistingChrome,
@@ -82,6 +82,8 @@ export function buildInterceptors(config: HtkConfig): _.Dictionary<Interceptor>
8282
new FreshOpera(config),
8383
new FreshBrave(config),
8484
new FreshFirefox(config),
85+
new FreshFirefoxDeveloper(config),
86+
new FreshFirefoxNightly(config),
8587

8688
new FreshTerminalInterceptor(config),
8789
new ExistingTerminalInterceptor(config),

test/integration/e2e-api-test.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,9 @@ describe('End-to-end server API test', function () {
264264
inactivable('fresh-edge-canary'),
265265
inactivable('fresh-opera', '1.0.3'),
266266
inactivable('fresh-brave'),
267-
activable('fresh-firefox', '1.1.0'),
267+
activable('fresh-firefox', '1.2.0'),
268+
inactivable('fresh-firefox-dev', '1.2.0'),
269+
inactivable('fresh-firefox-nightly', '1.2.0'),
268270
activable('fresh-terminal'),
269271
activable('existing-terminal'),
270272
activable('electron', '1.0.1'),

0 commit comments

Comments
 (0)