tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

chrome.ts (6459B)


      1 /**
      2 * @license
      3 * Copyright 2023 Google Inc.
      4 * SPDX-License-Identifier: Apache-2.0
      5 */
      6 
      7 import path from 'node:path';
      8 
      9 import semver from 'semver';
     10 
     11 import {getJSON} from '../httpUtil.js';
     12 
     13 import {BrowserPlatform, ChromeReleaseChannel} from './types.js';
     14 
     15 function folder(platform: BrowserPlatform): string {
     16  switch (platform) {
     17    case BrowserPlatform.LINUX_ARM:
     18    case BrowserPlatform.LINUX:
     19      return 'linux64';
     20    case BrowserPlatform.MAC_ARM:
     21      return 'mac-arm64';
     22    case BrowserPlatform.MAC:
     23      return 'mac-x64';
     24    case BrowserPlatform.WIN32:
     25      return 'win32';
     26    case BrowserPlatform.WIN64:
     27      return 'win64';
     28  }
     29 }
     30 
     31 export function resolveDownloadUrl(
     32  platform: BrowserPlatform,
     33  buildId: string,
     34  baseUrl = 'https://storage.googleapis.com/chrome-for-testing-public',
     35 ): string {
     36  return `${baseUrl}/${resolveDownloadPath(platform, buildId).join('/')}`;
     37 }
     38 
     39 export function resolveDownloadPath(
     40  platform: BrowserPlatform,
     41  buildId: string,
     42 ): string[] {
     43  return [buildId, folder(platform), `chrome-${folder(platform)}.zip`];
     44 }
     45 
     46 export function relativeExecutablePath(
     47  platform: BrowserPlatform,
     48  _buildId: string,
     49 ): string {
     50  switch (platform) {
     51    case BrowserPlatform.MAC:
     52    case BrowserPlatform.MAC_ARM:
     53      return path.join(
     54        'chrome-' + folder(platform),
     55        'Google Chrome for Testing.app',
     56        'Contents',
     57        'MacOS',
     58        'Google Chrome for Testing',
     59      );
     60    case BrowserPlatform.LINUX_ARM:
     61    case BrowserPlatform.LINUX:
     62      return path.join('chrome-linux64', 'chrome');
     63    case BrowserPlatform.WIN32:
     64    case BrowserPlatform.WIN64:
     65      return path.join('chrome-' + folder(platform), 'chrome.exe');
     66  }
     67 }
     68 
     69 export async function getLastKnownGoodReleaseForChannel(
     70  channel: ChromeReleaseChannel,
     71 ): Promise<{version: string; revision: string}> {
     72  const data = (await getJSON(
     73    new URL(
     74      'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json',
     75    ),
     76  )) as {
     77    channels: Record<string, {version: string}>;
     78  };
     79 
     80  for (const channel of Object.keys(data.channels)) {
     81    data.channels[channel.toLowerCase()] = data.channels[channel]!;
     82    delete data.channels[channel];
     83  }
     84 
     85  return (
     86    data as {
     87      channels: Record<
     88        ChromeReleaseChannel,
     89        {version: string; revision: string}
     90      >;
     91    }
     92  ).channels[channel];
     93 }
     94 
     95 export async function getLastKnownGoodReleaseForMilestone(
     96  milestone: string,
     97 ): Promise<{version: string; revision: string} | undefined> {
     98  const data = (await getJSON(
     99    new URL(
    100      'https://googlechromelabs.github.io/chrome-for-testing/latest-versions-per-milestone.json',
    101    ),
    102  )) as {
    103    milestones: Record<string, {version: string; revision: string}>;
    104  };
    105  return data.milestones[milestone] as
    106    | {version: string; revision: string}
    107    | undefined;
    108 }
    109 
    110 export async function getLastKnownGoodReleaseForBuild(
    111  /**
    112   * @example `112.0.23`,
    113   */
    114  buildPrefix: string,
    115 ): Promise<{version: string; revision: string} | undefined> {
    116  const data = (await getJSON(
    117    new URL(
    118      'https://googlechromelabs.github.io/chrome-for-testing/latest-patch-versions-per-build.json',
    119    ),
    120  )) as {
    121    builds: Record<string, {version: string; revision: string}>;
    122  };
    123  return data.builds[buildPrefix] as
    124    | {version: string; revision: string}
    125    | undefined;
    126 }
    127 
    128 export async function resolveBuildId(
    129  channel: ChromeReleaseChannel,
    130 ): Promise<string>;
    131 export async function resolveBuildId(
    132  channel: string,
    133 ): Promise<string | undefined>;
    134 export async function resolveBuildId(
    135  channel: ChromeReleaseChannel | string,
    136 ): Promise<string | undefined> {
    137  if (
    138    Object.values(ChromeReleaseChannel).includes(
    139      channel as ChromeReleaseChannel,
    140    )
    141  ) {
    142    return (
    143      await getLastKnownGoodReleaseForChannel(channel as ChromeReleaseChannel)
    144    ).version;
    145  }
    146  if (channel.match(/^\d+$/)) {
    147    // Potentially a milestone.
    148    return (await getLastKnownGoodReleaseForMilestone(channel))?.version;
    149  }
    150  if (channel.match(/^\d+\.\d+\.\d+$/)) {
    151    // Potentially a build prefix without the patch version.
    152    return (await getLastKnownGoodReleaseForBuild(channel))?.version;
    153  }
    154  return;
    155 }
    156 
    157 export function resolveSystemExecutablePath(
    158  platform: BrowserPlatform,
    159  channel: ChromeReleaseChannel,
    160 ): string {
    161  switch (platform) {
    162    case BrowserPlatform.WIN64:
    163    case BrowserPlatform.WIN32:
    164      switch (channel) {
    165        case ChromeReleaseChannel.STABLE:
    166          return `${process.env['PROGRAMFILES']}\\Google\\Chrome\\Application\\chrome.exe`;
    167        case ChromeReleaseChannel.BETA:
    168          return `${process.env['PROGRAMFILES']}\\Google\\Chrome Beta\\Application\\chrome.exe`;
    169        case ChromeReleaseChannel.CANARY:
    170          return `${process.env['PROGRAMFILES']}\\Google\\Chrome SxS\\Application\\chrome.exe`;
    171        case ChromeReleaseChannel.DEV:
    172          return `${process.env['PROGRAMFILES']}\\Google\\Chrome Dev\\Application\\chrome.exe`;
    173      }
    174    case BrowserPlatform.MAC_ARM:
    175    case BrowserPlatform.MAC:
    176      switch (channel) {
    177        case ChromeReleaseChannel.STABLE:
    178          return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
    179        case ChromeReleaseChannel.BETA:
    180          return '/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta';
    181        case ChromeReleaseChannel.CANARY:
    182          return '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary';
    183        case ChromeReleaseChannel.DEV:
    184          return '/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev';
    185      }
    186    case BrowserPlatform.LINUX_ARM:
    187    case BrowserPlatform.LINUX:
    188      switch (channel) {
    189        case ChromeReleaseChannel.STABLE:
    190          return '/opt/google/chrome/chrome';
    191        case ChromeReleaseChannel.BETA:
    192          return '/opt/google/chrome-beta/chrome';
    193        case ChromeReleaseChannel.CANARY:
    194          return '/opt/google/chrome-canary/chrome';
    195        case ChromeReleaseChannel.DEV:
    196          return '/opt/google/chrome-unstable/chrome';
    197      }
    198  }
    199 }
    200 
    201 export function compareVersions(a: string, b: string): number {
    202  if (!semver.valid(a)) {
    203    throw new Error(`Version ${a} is not a valid semver version`);
    204  }
    205  if (!semver.valid(b)) {
    206    throw new Error(`Version ${b} is not a valid semver version`);
    207  }
    208  if (semver.gt(a, b)) {
    209    return 1;
    210  } else if (semver.lt(a, b)) {
    211    return -1;
    212  } else {
    213    return 0;
    214  }
    215 }