brave-real-launcher 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -72,8 +72,37 @@ jobs:
72
72
  run: |
73
73
  echo "🔍 Checking for chrome-launcher updates..."
74
74
 
75
- # Chrome-launcher की latest version fetch करें
76
- CHROME_VERSION=$(curl -s https://api.github.com/repos/GoogleChrome/chrome-launcher/releases/latest | jq -r .tag_name | sed 's/v//')
75
+ # Chrome-launcher की latest version fetch करें with error handling
76
+ echo "🔍 Fetching chrome-launcher latest release..."
77
+
78
+ # Fetch chrome-launcher version with multiple methods
79
+ CHROME_VERSION=""
80
+
81
+ # Method 1: Try GitHub API
82
+ if command -v jq >/dev/null 2>&1; then
83
+ CHROME_API_RESPONSE=$(curl -s "https://api.github.com/repos/GoogleChrome/chrome-launcher/releases/latest")
84
+ if echo "$CHROME_API_RESPONSE" | jq -e '.tag_name' >/dev/null 2>&1; then
85
+ CHROME_VERSION=$(echo "$CHROME_API_RESPONSE" | jq -r .tag_name | sed 's/v//')
86
+ echo "✅ Found chrome-launcher version via GitHub API: $CHROME_VERSION"
87
+ fi
88
+ fi
89
+
90
+ # Method 2: Fallback to NPM registry
91
+ if [ -z "$CHROME_VERSION" ] || [ "$CHROME_VERSION" = "null" ]; then
92
+ echo "⚠️ GitHub API failed, trying NPM registry..."
93
+ CHROME_VERSION=$(curl -s "https://registry.npmjs.org/chrome-launcher/latest" | jq -r .version 2>/dev/null || echo "")
94
+ if [ -n "$CHROME_VERSION" ] && [ "$CHROME_VERSION" != "null" ]; then
95
+ echo "✅ Found chrome-launcher version via NPM: $CHROME_VERSION"
96
+ fi
97
+ fi
98
+
99
+ # Method 3: Final fallback - use current version
100
+ if [ -z "$CHROME_VERSION" ] || [ "$CHROME_VERSION" = "null" ]; then
101
+ echo "⚠️ All methods failed, using current version as fallback"
102
+ CHROME_VERSION=$(node -e "console.log(require('./package.json').version)")
103
+ echo "📦 Fallback to current version: $CHROME_VERSION"
104
+ fi
105
+
77
106
  CURRENT_VERSION=$(node -e "console.log(require('./package.json').version)")
78
107
 
79
108
  echo "chrome_version=$CHROME_VERSION" >> $GITHUB_OUTPUT
@@ -102,10 +131,27 @@ jobs:
102
131
  - name: 🔄 Sync with Chrome-Launcher
103
132
  if: steps.sync-check.outputs.should_sync == 'true'
104
133
  run: |
105
- echo "🔄 Syncing brave-real-launcher with chrome-launcher v${{ steps.sync-check.outputs.chrome_version }}"
134
+ echo "🔢 Syncing brave-real-launcher with chrome-launcher v${{ steps.sync-check.outputs.chrome_version }}"
135
+
136
+ # Validate chrome version before using it
137
+ CHROME_VER="${{ steps.sync-check.outputs.chrome_version }}"
138
+ if [ "$CHROME_VER" = "null" ] || [ -z "$CHROME_VER" ]; then
139
+ echo "❌ Invalid chrome version detected: $CHROME_VER"
140
+ echo "🔄 Skipping sync due to invalid version"
141
+ exit 0
142
+ fi
143
+
144
+ # Validate version format (should be x.y.z)
145
+ if ! echo "$CHROME_VER" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$'; then
146
+ echo "❌ Invalid version format: $CHROME_VER"
147
+ echo "🔄 Skipping sync due to invalid version format"
148
+ exit 0
149
+ fi
150
+
151
+ echo "✅ Valid chrome version: $CHROME_VER"
106
152
 
107
153
  # Package.json version को update करें
108
- npm version ${{ steps.sync-check.outputs.chrome_version }} --no-git-tag-version
154
+ npm version "$CHROME_VER" --no-git-tag-version
109
155
 
110
156
  # Git configuration
111
157
  git config user.name "🤖 Brave Sync Bot"
@@ -198,55 +244,136 @@ jobs:
198
244
  npm audit --audit-level high || echo "⚠️ Some security issues found but continuing..."
199
245
  echo "✅ Security audit completed!"
200
246
 
201
- # Step 10: Determine publish strategy
202
- - name: 🎯 Determine Publish Strategy
203
- id: publish-check
247
+ # Step 10: Smart Version Management & Publish Strategy
248
+ - name: 🔢 Smart Version Management
249
+ id: version-manager
204
250
  run: |
205
- echo "🎯 Determining publish strategy..."
251
+ echo "🔢 Smart version management starting..."
206
252
 
253
+ # Get current status
207
254
  PUBLISH_MODE="${{ github.event.inputs.publish_mode || 'auto' }}"
208
- SHOULD_PUBLISH="false"
209
- REASON=""
255
+ SYNC_PERFORMED="${{ steps.sync-check.outputs.should_sync }}"
256
+ CHROME_VERSION="${{ steps.sync-check.outputs.chrome_version }}"
210
257
 
211
- # Current और NPM version check करें
258
+ # Current version from package.json
212
259
  CURRENT_VERSION=$(node -e "console.log(require('./package.json').version)")
260
+
261
+ # NPM published version
262
+ echo "📎 Checking NPM registry..."
213
263
  NPM_VERSION=$(npm view brave-real-launcher version 2>/dev/null || echo "0.0.0")
214
264
 
215
- echo "Current version: $CURRENT_VERSION"
265
+ echo "=== Version Status ==="
266
+ echo "Local version: $CURRENT_VERSION"
216
267
  echo "NPM version: $NPM_VERSION"
268
+ echo "Chrome-launcher version: $CHROME_VERSION"
269
+ echo "Sync performed: $SYNC_PERFORMED"
270
+ echo "Publish mode: $PUBLISH_MODE"
271
+
272
+ # Smart version determination
273
+ NEW_VERSION=""
274
+ SHOULD_PUBLISH="false"
275
+ REASON=""
217
276
 
218
- # Publish logic
219
277
  if [ "$PUBLISH_MODE" = "skip" ]; then
278
+ SHOULD_PUBLISH="false"
220
279
  REASON="Publish mode set to skip"
221
- elif [ "$PUBLISH_MODE" = "force" ]; then
280
+ NEW_VERSION="$CURRENT_VERSION"
281
+
282
+ elif [ "$SYNC_PERFORMED" = "true" ]; then
283
+ # Chrome-launcher sync हुआ है - use chrome version
284
+ NEW_VERSION="$CHROME_VERSION"
222
285
  SHOULD_PUBLISH="true"
223
- REASON="Force publish requested"
224
- elif [ "$PUBLISH_MODE" = "auto" ]; then
225
- if [ "$CURRENT_VERSION" != "$NPM_VERSION" ]; then
226
- # Only publish on main/master branch for auto mode
227
- if [[ "${{ github.ref }}" == "refs/heads/main" || "${{ github.ref }}" == "refs/heads/master" ]]; then
286
+ REASON="Synced with chrome-launcher v$CHROME_VERSION"
287
+
288
+ # Update package.json with chrome version
289
+ if [ "$NEW_VERSION" != "$CURRENT_VERSION" ]; then
290
+ echo "🔄 Updating package.json to chrome-launcher version: $NEW_VERSION"
291
+ npm version "$NEW_VERSION" --no-git-tag-version
292
+ fi
293
+
294
+ else
295
+ # Regular update - सिर्फ main/master branch पर publish करें
296
+ if [[ "${{ github.ref }}" == "refs/heads/main" || "${{ github.ref }}" == "refs/heads/master" ]]; then
297
+
298
+ if [ "$NPM_VERSION" = "0.0.0" ]; then
299
+ # First publish
300
+ NEW_VERSION="$CURRENT_VERSION"
228
301
  SHOULD_PUBLISH="true"
229
- REASON="Version updated from $NPM_VERSION to $CURRENT_VERSION"
302
+ REASON="First publish"
230
303
  else
231
- REASON="Version changed but not on main branch"
304
+ # Auto-increment करें अगर NPM version >= current version
305
+ if [ "$(printf '%s\n' "$NPM_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$NPM_VERSION" ]; then
306
+ # NPM version is same or newer, increment
307
+ echo "🔢 Auto-incrementing patch version..."
308
+
309
+ # Parse NPM version and increment
310
+ IFS='.' read -r major minor patch <<< "$NPM_VERSION"
311
+ NEW_PATCH=$((patch + 1))
312
+ NEW_VERSION="${major}.${minor}.${NEW_PATCH}"
313
+
314
+ echo "📈 Version increment: $NPM_VERSION → $NEW_VERSION"
315
+
316
+ # Update package.json
317
+ npm version "$NEW_VERSION" --no-git-tag-version
318
+
319
+ SHOULD_PUBLISH="true"
320
+ REASON="Auto-incremented from $NPM_VERSION to $NEW_VERSION"
321
+ else
322
+ # Current version is newer
323
+ NEW_VERSION="$CURRENT_VERSION"
324
+ SHOULD_PUBLISH="true"
325
+ REASON="Local version newer than NPM: $CURRENT_VERSION > $NPM_VERSION"
326
+ fi
232
327
  fi
328
+
233
329
  else
234
- REASON="No version change detected"
330
+ # Not on main branch
331
+ NEW_VERSION="$CURRENT_VERSION"
332
+ SHOULD_PUBLISH="false"
333
+ REASON="Not on main/master branch"
334
+ fi
335
+ fi
336
+
337
+ # Force publish override
338
+ if [ "$PUBLISH_MODE" = "force" ]; then
339
+ if [ -z "$NEW_VERSION" ] || [ "$NEW_VERSION" = "$CURRENT_VERSION" ]; then
340
+ # Force के लिए increment करें
341
+ IFS='.' read -r major minor patch <<< "$([ "$NPM_VERSION" != "0.0.0" ] && echo "$NPM_VERSION" || echo "$CURRENT_VERSION")"
342
+ NEW_PATCH=$((patch + 1))
343
+ NEW_VERSION="${major}.${minor}.${NEW_PATCH}"
344
+ npm version "$NEW_VERSION" --no-git-tag-version
235
345
  fi
346
+ SHOULD_PUBLISH="true"
347
+ REASON="Force publish requested - v$NEW_VERSION"
348
+ fi
349
+
350
+ # Commit version changes if made
351
+ if [ "$NEW_VERSION" != "$CURRENT_VERSION" ]; then
352
+ echo "📁 Committing version change..."
353
+ git config user.name "🤖 Brave Version Manager"
354
+ git config user.email "action@github.com"
355
+ git add package.json package-lock.json
356
+ git commit -m "🔢 Version update: $CURRENT_VERSION → $NEW_VERSION" || echo "No changes to commit"
357
+ git push || echo "Nothing to push"
236
358
  fi
237
359
 
360
+ # Output results
238
361
  echo "should_publish=$SHOULD_PUBLISH" >> $GITHUB_OUTPUT
239
362
  echo "reason=$REASON" >> $GITHUB_OUTPUT
240
- echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
241
- echo "npm_version=$NPM_VERSION" >> $GITHUB_OUTPUT
363
+ echo "final_version=$NEW_VERSION" >> $GITHUB_OUTPUT
364
+ echo "version_changed=$([ "$NEW_VERSION" != "$CURRENT_VERSION" ] && echo "true" || echo "false")" >> $GITHUB_OUTPUT
242
365
 
243
- echo "📋 Publish decision: $SHOULD_PUBLISH ($REASON)"
366
+ echo "=== Final Decision ==="
367
+ echo "📋 Should publish: $SHOULD_PUBLISH"
368
+ echo "📋 Final version: $NEW_VERSION"
369
+ echo "📋 Reason: $REASON"
244
370
 
245
371
  # Step 11: Publish to NPM
246
372
  - name: 🚀 Publish to NPM
247
- if: steps.publish-check.outputs.should_publish == 'true'
373
+ if: steps.version-manager.outputs.should_publish == 'true'
248
374
  run: |
249
- echo "🚀 Publishing brave-real-launcher v${{ steps.publish-check.outputs.current_version }} to NPM..."
375
+ FINAL_VERSION="${{ steps.version-manager.outputs.final_version }}"
376
+ echo "🚀 Publishing brave-real-launcher v$FINAL_VERSION to NPM..."
250
377
 
251
378
  # Verify we have NPM token
252
379
  if [ -z "$NPM_TOKEN" ]; then
@@ -263,12 +390,12 @@ jobs:
263
390
  git config user.name "🤖 Brave Publish Bot"
264
391
  git config user.email "action@github.com"
265
392
 
266
- TAG_NAME="v${{ steps.publish-check.outputs.current_version }}"
393
+ TAG_NAME="v$FINAL_VERSION"
267
394
  git tag "$TAG_NAME" || echo "Tag might already exist"
268
395
  git push origin "$TAG_NAME" || echo "Failed to push tag"
269
396
  fi
270
397
 
271
- echo "🎉 Successfully published brave-real-launcher v${{ steps.publish-check.outputs.current_version }}!"
398
+ echo "🎉 Successfully published brave-real-launcher v$FINAL_VERSION!"
272
399
  env:
273
400
  NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
274
401
  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -280,19 +407,20 @@ jobs:
280
407
  echo "=================================="
281
408
  echo "📋 Execution Summary:"
282
409
  echo "• Chrome-launcher version: ${{ steps.sync-check.outputs.chrome_version }}"
283
- echo "• Our version: ${{ steps.publish-check.outputs.current_version }}"
410
+ echo "• Final version: ${{ steps.version-manager.outputs.final_version }}"
411
+ echo "• Version changed: ${{ steps.version-manager.outputs.version_changed }}"
284
412
  echo "• Sync performed: ${{ steps.sync-check.outputs.should_sync }}"
285
413
  echo "• Sync mode: ${{ steps.sync-check.outputs.sync_mode }}"
286
- echo "• Publish performed: ${{ steps.publish-check.outputs.should_publish }}"
287
- echo "• Publish reason: ${{ steps.publish-check.outputs.reason }}"
414
+ echo "• Publish performed: ${{ steps.version-manager.outputs.should_publish }}"
415
+ echo "• Publish reason: ${{ steps.version-manager.outputs.reason }}"
288
416
  echo "• Build: ✅ Success"
289
417
  echo "• Tests: ✅ Passed"
290
418
  echo "• Security: ✅ Checked"
291
419
  echo "=================================="
292
420
 
293
421
  # Set workflow status
294
- if [ "${{ steps.publish-check.outputs.should_publish }}" = "true" ]; then
295
- echo "🚀 Package published successfully!"
422
+ if [ "${{ steps.version-manager.outputs.should_publish }}" = "true" ]; then
423
+ echo "🚀 Package published successfully as v${{ steps.version-manager.outputs.final_version }}!"
296
424
  else
297
- echo "📦 Package ready but not published (${{ steps.publish-check.outputs.reason }})"
298
- fi
425
+ echo "📦 Package ready but not published (${{ steps.version-manager.outputs.reason }})"
426
+ fi
@@ -0,0 +1,341 @@
1
+ /**
2
+ * @license Copyright 2016 Google Inc. All Rights Reserved.
3
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5
+ */
6
+ 'use strict';
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ import { homedir } from 'os';
10
+ import { execSync } from 'child_process';
11
+ import escapeRegExp from 'escape-string-regexp';
12
+ import log from 'lighthouse-logger';
13
+ import which from 'which';
14
+ import { getWSLLocalAppDataPath, toWSLPath, BravePathNotSetError } from './utils.mjs.mjs';
15
+ const newLineRegex = /\r?\n/;
16
+ /**
17
+ * check for macOS default app paths first to avoid waiting for the slow lsregister command
18
+ */
19
+ export function darwinFast() {
20
+ const priorityOptions = [
21
+ process.env.BRAVE_PATH,
22
+ process.env.LIGHTHOUSE_BRAVE_PATH,
23
+ // Brave Browser paths
24
+ '/Applications/Brave Browser.app/Contents/MacOS/Brave Browser',
25
+ '/Applications/Brave Browser Beta.app/Contents/MacOS/Brave Browser Beta',
26
+ '/Applications/Brave Browser Nightly.app/Contents/MacOS/Brave Browser Nightly',
27
+ '/Applications/Brave Browser Dev.app/Contents/MacOS/Brave Browser Dev',
28
+ ];
29
+ for (const bravePath of priorityOptions) {
30
+ if (bravePath && canAccess(bravePath))
31
+ return bravePath;
32
+ }
33
+ return darwin()[0];
34
+ }
35
+ export function darwin() {
36
+ const suffixes = [
37
+ '/Contents/MacOS/Brave Browser',
38
+ '/Contents/MacOS/Brave Browser Beta',
39
+ '/Contents/MacOS/Brave Browser Nightly',
40
+ '/Contents/MacOS/Brave Browser Dev'
41
+ ];
42
+ const LSREGISTER = '/System/Library/Frameworks/CoreServices.framework' +
43
+ '/Versions/A/Frameworks/LaunchServices.framework' +
44
+ '/Versions/A/Support/lsregister';
45
+ const installations = [];
46
+ const customBravePath = resolveBravePath();
47
+ if (customBravePath) {
48
+ installations.push(customBravePath);
49
+ }
50
+ // Look for Brave Browser installations
51
+ try {
52
+ execSync(`${LSREGISTER} -dump` +
53
+ ' | grep -i \'brave browser\\( beta\\| nightly\\| dev\\)\\?\\.app\'' +
54
+ ' | awk \'{$1=""; print $0}\'')
55
+ .toString()
56
+ .split(newLineRegex)
57
+ .forEach((inst) => {
58
+ suffixes.forEach(suffix => {
59
+ const execPath = path.join(inst.substring(0, inst.indexOf('.app') + 4).trim(), suffix);
60
+ if (canAccess(execPath) && installations.indexOf(execPath) === -1) {
61
+ installations.push(execPath);
62
+ }
63
+ });
64
+ });
65
+ }
66
+ catch (e) {
67
+ // lsregister might not be available or might fail
68
+ log.warn('BraveLauncher', 'lsregister command failed, checking default paths');
69
+ }
70
+ // Retains one per line to maintain readability.
71
+ // clang-format off
72
+ const home = escapeRegExp(process.env.HOME || homedir());
73
+ const priorities = [
74
+ { regex: new RegExp(`^${home}/Applications/.*Brave Browser\\.app`), weight: 50 },
75
+ { regex: new RegExp(`^${home}/Applications/.*Brave Browser Beta\\.app`), weight: 51 },
76
+ { regex: new RegExp(`^${home}/Applications/.*Brave Browser Nightly\\.app`), weight: 52 },
77
+ { regex: new RegExp(`^${home}/Applications/.*Brave Browser Dev\\.app`), weight: 53 },
78
+ { regex: /^\/Applications\/.*Brave Browser\.app/, weight: 100 },
79
+ { regex: /^\/Applications\/.*Brave Browser Beta\.app/, weight: 101 },
80
+ { regex: /^\/Applications\/.*Brave Browser Nightly\.app/, weight: 102 },
81
+ { regex: /^\/Applications\/.*Brave Browser Dev\.app/, weight: 103 },
82
+ { regex: /^\/Volumes\/.*Brave Browser\.app/, weight: -2 },
83
+ { regex: /^\/Volumes\/.*Brave Browser Beta\.app/, weight: -1 },
84
+ ];
85
+ if (process.env.LIGHTHOUSE_BRAVE_PATH) {
86
+ priorities.unshift({ regex: new RegExp(escapeRegExp(process.env.LIGHTHOUSE_BRAVE_PATH)), weight: 150 });
87
+ }
88
+ if (process.env.BRAVE_PATH) {
89
+ priorities.unshift({ regex: new RegExp(escapeRegExp(process.env.BRAVE_PATH)), weight: 151 });
90
+ }
91
+ // clang-format on
92
+ return sort(installations, priorities);
93
+ }
94
+ function resolveBravePath() {
95
+ if (canAccess(process.env.BRAVE_PATH)) {
96
+ return process.env.BRAVE_PATH;
97
+ }
98
+ if (canAccess(process.env.LIGHTHOUSE_BRAVE_PATH)) {
99
+ log.warn('BraveLauncher', 'LIGHTHOUSE_BRAVE_PATH is deprecated, use BRAVE_PATH env variable instead.');
100
+ return process.env.LIGHTHOUSE_BRAVE_PATH;
101
+ }
102
+ return undefined;
103
+ }
104
+ /**
105
+ * Look for linux executables in 3 ways
106
+ * 1. Look into BRAVE_PATH env variable
107
+ * 2. Look into the directories where .desktop are saved on gnome based distro's
108
+ * 3. Look for brave-browser & brave executables by using the which command
109
+ * Support for both x64 and ARM64 architectures
110
+ */
111
+ export function linux() {
112
+ let installations = [];
113
+ // 1. Look into BRAVE_PATH env variable
114
+ const customBravePath = resolveBravePath();
115
+ if (customBravePath) {
116
+ installations.push(customBravePath);
117
+ }
118
+ // 2. Look into the directories where .desktop are saved on gnome based distro's
119
+ const desktopInstallationFolders = [
120
+ path.join(homedir(), '.local/share/applications/'),
121
+ '/usr/share/applications/',
122
+ ];
123
+ desktopInstallationFolders.forEach(folder => {
124
+ installations = installations.concat(findBraveExecutables(folder));
125
+ });
126
+ // 3. Look for brave-browser, brave, and other brave executables by using the which command
127
+ const executables = [
128
+ 'brave-browser',
129
+ 'brave-browser-stable',
130
+ 'brave-browser-beta',
131
+ 'brave-browser-nightly',
132
+ 'brave-browser-dev',
133
+ 'brave',
134
+ 'brave-stable',
135
+ 'brave-beta',
136
+ 'brave-nightly',
137
+ 'brave-dev',
138
+ // Flatpak versions
139
+ 'flatpak run com.brave.Browser',
140
+ // Snap versions
141
+ 'brave',
142
+ ];
143
+ // Check standard installation paths for different architectures
144
+ const standardPaths = [
145
+ '/usr/bin/brave-browser',
146
+ '/usr/bin/brave-browser-stable',
147
+ '/usr/bin/brave-browser-beta',
148
+ '/usr/bin/brave-browser-nightly',
149
+ '/usr/bin/brave',
150
+ '/opt/brave.com/brave/brave',
151
+ '/opt/brave.com/brave-beta/brave-beta',
152
+ '/opt/brave.com/brave-nightly/brave-nightly',
153
+ '/opt/brave.com/brave-dev/brave-dev',
154
+ '/snap/bin/brave',
155
+ // ARM64 specific paths
156
+ '/usr/lib/aarch64-linux-gnu/brave/brave',
157
+ '/opt/brave-browser/brave',
158
+ // Additional paths for different distros
159
+ '/usr/local/bin/brave',
160
+ '/usr/local/bin/brave-browser',
161
+ ];
162
+ standardPaths.forEach(bravePath => {
163
+ if (canAccess(bravePath)) {
164
+ installations.push(bravePath);
165
+ }
166
+ });
167
+ executables.forEach((executable) => {
168
+ try {
169
+ const bravePath = which.sync(executable, { nothrow: true });
170
+ if (bravePath && canAccess(bravePath)) {
171
+ installations.push(bravePath);
172
+ }
173
+ }
174
+ catch (e) {
175
+ // Not installed.
176
+ }
177
+ });
178
+ if (!installations.length) {
179
+ throw new BravePathNotSetError();
180
+ }
181
+ const priorities = [
182
+ { regex: /brave-wrapper$/, weight: 51 },
183
+ { regex: /brave-browser-stable$/, weight: 50 },
184
+ { regex: /brave-browser$/, weight: 49 },
185
+ { regex: /brave-stable$/, weight: 48 },
186
+ { regex: /brave$/, weight: 47 },
187
+ { regex: /brave-browser-beta$/, weight: 46 },
188
+ { regex: /brave-beta$/, weight: 45 },
189
+ { regex: /brave-browser-nightly$/, weight: 44 },
190
+ { regex: /brave-nightly$/, weight: 43 },
191
+ { regex: /brave-browser-dev$/, weight: 42 },
192
+ { regex: /brave-dev$/, weight: 41 },
193
+ ];
194
+ if (process.env.LIGHTHOUSE_BRAVE_PATH) {
195
+ priorities.unshift({ regex: new RegExp(escapeRegExp(process.env.LIGHTHOUSE_BRAVE_PATH)), weight: 100 });
196
+ }
197
+ if (process.env.BRAVE_PATH) {
198
+ priorities.unshift({ regex: new RegExp(escapeRegExp(process.env.BRAVE_PATH)), weight: 101 });
199
+ }
200
+ return sort(uniq(installations.filter(Boolean)), priorities);
201
+ }
202
+ export function wsl() {
203
+ // Manually populate the environment variables assuming it's the default config
204
+ process.env.LOCALAPPDATA = getWSLLocalAppDataPath(`${process.env.PATH}`);
205
+ process.env.PROGRAMFILES = toWSLPath('C:/Program Files', '/mnt/c/Program Files');
206
+ process.env['PROGRAMFILES(X86)'] =
207
+ toWSLPath('C:/Program Files (x86)', '/mnt/c/Program Files (x86)');
208
+ return win32();
209
+ }
210
+ export function win32() {
211
+ const installations = [];
212
+ // Brave Browser installation paths for different architectures
213
+ const suffixes = [
214
+ // Standard x64 installations
215
+ `${path.sep}BraveSoftware${path.sep}Brave-Browser${path.sep}Application${path.sep}brave.exe`,
216
+ `${path.sep}BraveSoftware${path.sep}Brave-Browser-Beta${path.sep}Application${path.sep}brave.exe`,
217
+ `${path.sep}BraveSoftware${path.sep}Brave-Browser-Nightly${path.sep}Application${path.sep}brave.exe`,
218
+ `${path.sep}BraveSoftware${path.sep}Brave-Browser-Dev${path.sep}Application${path.sep}brave.exe`,
219
+ // Alternative paths
220
+ `${path.sep}Brave${path.sep}Application${path.sep}brave.exe`,
221
+ `${path.sep}Brave-Browser${path.sep}Application${path.sep}brave.exe`,
222
+ ];
223
+ const prefixes = [
224
+ process.env.LOCALAPPDATA,
225
+ process.env.PROGRAMFILES,
226
+ process.env['PROGRAMFILES(X86)'],
227
+ // Additional paths for ARM64 and other architectures
228
+ process.env.PROGRAMW6432,
229
+ ].filter(Boolean);
230
+ const customBravePath = resolveBravePath();
231
+ if (customBravePath) {
232
+ installations.push(customBravePath);
233
+ }
234
+ // Check standard installation paths
235
+ prefixes.forEach(prefix => suffixes.forEach(suffix => {
236
+ const bravePath = path.join(prefix, suffix);
237
+ if (canAccess(bravePath)) {
238
+ installations.push(bravePath);
239
+ }
240
+ }));
241
+ // Check Windows Registry for Brave installations
242
+ try {
243
+ const registryPaths = getWindowsRegistryBravePaths();
244
+ registryPaths.forEach(regPath => {
245
+ if (canAccess(regPath)) {
246
+ installations.push(regPath);
247
+ }
248
+ });
249
+ }
250
+ catch (e) {
251
+ log.warn('BraveLauncher', 'Failed to read Windows registry for Brave paths');
252
+ }
253
+ return installations;
254
+ }
255
+ function getWindowsRegistryBravePaths() {
256
+ const paths = [];
257
+ // Registry keys where Brave might be registered
258
+ const registryKeys = [
259
+ 'HKEY_LOCAL_MACHINE\\SOFTWARE\\BraveSoftware\\Brave',
260
+ 'HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\BraveSoftware\\Brave',
261
+ 'HKEY_CURRENT_USER\\SOFTWARE\\BraveSoftware\\Brave',
262
+ 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\brave.exe',
263
+ ];
264
+ registryKeys.forEach(key => {
265
+ try {
266
+ const result = execSync(`reg query "${key}" /ve 2>nul`, { encoding: 'utf-8' });
267
+ const match = result.match(/REG_SZ\s+(.+)/);
268
+ if (match && match[1]) {
269
+ const bravePath = match[1].trim();
270
+ if (bravePath && canAccess(bravePath)) {
271
+ paths.push(bravePath);
272
+ }
273
+ }
274
+ }
275
+ catch (e) {
276
+ // Registry key doesn't exist or access denied
277
+ }
278
+ });
279
+ return paths;
280
+ }
281
+ function sort(installations, priorities) {
282
+ const defaultPriority = 10;
283
+ return installations
284
+ // assign priorities
285
+ .map((inst) => {
286
+ for (const pair of priorities) {
287
+ if (pair.regex.test(inst)) {
288
+ return { path: inst, weight: pair.weight };
289
+ }
290
+ }
291
+ return { path: inst, weight: defaultPriority };
292
+ })
293
+ // sort based on priorities
294
+ .sort((a, b) => (b.weight - a.weight))
295
+ // remove priority flag
296
+ .map(pair => pair.path);
297
+ }
298
+ function canAccess(file) {
299
+ if (!file) {
300
+ return false;
301
+ }
302
+ try {
303
+ fs.accessSync(file);
304
+ return true;
305
+ }
306
+ catch (e) {
307
+ return false;
308
+ }
309
+ }
310
+ function uniq(arr) {
311
+ return Array.from(new Set(arr));
312
+ }
313
+ function findBraveExecutables(folder) {
314
+ const argumentsRegex = /(^[^ ]+).*/; // Take everything up to the first space
315
+ const braveExecRegex = '^Exec=\\/.*\\/(brave|brave-browser|brave-browser-stable|brave-browser-beta|brave-browser-nightly)-.*';
316
+ let installations = [];
317
+ if (canAccess(folder)) {
318
+ // Output of the grep & print looks like:
319
+ // /opt/brave.com/brave/brave --profile-directory
320
+ // /home/user/Downloads/brave-linux/brave-wrapper %U
321
+ let execPaths;
322
+ // Some systems do not support grep -R so fallback to -r.
323
+ try {
324
+ execPaths = execSync(`grep -ER "${braveExecRegex}" ${folder} | awk -F '=' '{print $2}'`, { stdio: 'pipe' });
325
+ }
326
+ catch (e) {
327
+ try {
328
+ execPaths = execSync(`grep -Er "${braveExecRegex}" ${folder} | awk -F '=' '{print $2}'`, { stdio: 'pipe' });
329
+ }
330
+ catch (e2) {
331
+ return installations;
332
+ }
333
+ }
334
+ execPaths = execPaths.toString()
335
+ .split(newLineRegex)
336
+ .map((execPath) => execPath.replace(argumentsRegex, '$1'));
337
+ execPaths.forEach((execPath) => canAccess(execPath) && installations.push(execPath));
338
+ }
339
+ return installations;
340
+ }
341
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJhdmUtZmluZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2JyYXZlLWZpbmRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsWUFBWSxDQUFDO0FBRWIsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3BCLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sSUFBSSxDQUFDO0FBQzNCLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDdkMsT0FBTyxZQUFZLE1BQU0sc0JBQXNCLENBQUM7QUFDaEQsT0FBTyxHQUFHLE1BQU0sbUJBQW1CLENBQUM7QUFDcEMsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBRTFCLE9BQU8sRUFBQyxzQkFBc0IsRUFBRSxTQUFTLEVBQUUsb0JBQW9CLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFFbkYsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDO0FBSTdCOztHQUVHO0FBQ0gsTUFBTSxVQUFVLFVBQVU7SUFDeEIsTUFBTSxlQUFlLEdBQTRCO1FBQy9DLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVTtRQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLHFCQUFxQjtRQUNqQyxzQkFBc0I7UUFDdEIsOERBQThEO1FBQzlELHdFQUF3RTtRQUN4RSw4RUFBOEU7UUFDOUUsc0VBQXNFO0tBQ3ZFLENBQUM7SUFFRixLQUFLLE1BQU0sU0FBUyxJQUFJLGVBQWUsRUFBRTtRQUN2QyxJQUFJLFNBQVMsSUFBSSxTQUFTLENBQUMsU0FBUyxDQUFDO1lBQUUsT0FBTyxTQUFTLENBQUM7S0FDekQ7SUFFRCxPQUFPLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO0FBQ3BCLENBQUM7QUFFRCxNQUFNLFVBQVUsTUFBTTtJQUNwQixNQUFNLFFBQVEsR0FBRztRQUNmLCtCQUErQjtRQUMvQixvQ0FBb0M7UUFDcEMsdUNB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