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