1import os from 'os';
2
3import { LaunchBrowserTypes, type LaunchBrowserInstance } from './LaunchBrowser.types';
4import LaunchBrowserImplLinux from './LaunchBrowserImplLinux';
5import LaunchBrowserImplMacOS from './LaunchBrowserImplMacOS';
6import LaunchBrowserImplWindows from './LaunchBrowserImplWindows';
7
8export type { LaunchBrowserInstance };
9
10const IS_WSL = require('is-wsl') && !require('is-docker')();
11
12/**
13 * Launch a browser for JavaScript inspector
14 */
15export async function launchBrowserAsync(url: string): Promise<LaunchBrowserInstance> {
16  const browser = createBrowser();
17  const tempBrowserDir = await browser.createTempBrowserDir('expo-inspector');
18
19  // For dev-client connecting metro in LAN, the request to fetch sourcemaps may be blocked by Chromium
20  // with insecure-content (https page send xhr for http resource).
21  // Adding `--allow-running-insecure-content` to overcome this limitation
22  // without users manually allow insecure-content in site settings.
23  // However, if there is existing chromium browser process, the argument will not take effect.
24  // We also pass a `--user-data-dir=` as temporary profile and force chromium to create new browser process.
25  const launchArgs = [
26    `--app=${url}`,
27    '--allow-running-insecure-content',
28    `--user-data-dir=${tempBrowserDir}`,
29    '--no-first-run',
30    '--no-default-browser-check',
31  ];
32
33  for (const browserType of [LaunchBrowserTypes.CHROME, LaunchBrowserTypes.EDGE]) {
34    const isSupported = await browser.isSupportedBrowser(browserType);
35    if (isSupported) {
36      return browser.launchAsync(browserType, launchArgs);
37    }
38  }
39
40  throw new Error(
41    '[LaunchBrowser] Unable to find a browser on the host to open the inspector. Supported browsers: Google Chrome, Microsoft Edge'
42  );
43}
44
45function createBrowser() {
46  if (os.platform() === 'darwin') {
47    return new LaunchBrowserImplMacOS();
48  }
49  if (os.platform() === 'win32' || IS_WSL) {
50    return new LaunchBrowserImplWindows();
51  }
52  if (os.platform() === 'linux') {
53    return new LaunchBrowserImplLinux();
54  }
55  throw new Error('[LaunchBrowser] Unsupported host platform');
56}
57