@dsh-sup/dsh-core-linux-x64 0.1.6-BETA.12 → 0.1.6-BETA.13
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.
- package/core.cjs +741 -236
- package/package.json +1 -1
- package/ui-react/assets/{InstancesPage-DadqCqud.js → InstancesPage-DM0dMQHh.js} +1 -1
- package/ui-react/assets/{LanPage-DWzQ-VLz.js → LanPage-B5oThF8O.js} +1 -1
- package/ui-react/assets/{OverviewPage-D9y-GeR2.js → OverviewPage-DH8PtnPI.js} +1 -1
- package/ui-react/assets/{PluginsPage-BwLIhj7E.js → PluginsPage-C1llxTDk.js} +1 -1
- package/ui-react/assets/{RouterPage-BeMIxdSL.js → RouterPage-CUKMV2Q9.js} +1 -1
- package/ui-react/assets/{SettingsPage-R7lkiQwq.js → SettingsPage-BZG-EvR3.js} +1 -1
- package/ui-react/assets/{TasksPage-A3SFro8F.js → TasksPage-haZMZbBh.js} +1 -1
- package/ui-react/assets/openExternal-CzqErnSy.js +1 -0
- package/ui-react/assets/{supervisor-Btn_MIEc.js → supervisor-BCZW2z-5.js} +2 -2
- package/ui-react/supervisor.html +1 -1
- package/ui-react/assets/openExternal-DOkxrLUq.js +0 -1
package/core.cjs
CHANGED
|
@@ -947,7 +947,7 @@ var require_version = __commonJS({
|
|
|
947
947
|
var fs2 = require("node:fs");
|
|
948
948
|
var path2 = require("node:path");
|
|
949
949
|
function guardVersion() {
|
|
950
|
-
if (true) return String("0.1.6-BETA.
|
|
950
|
+
if (true) return String("0.1.6-BETA.13");
|
|
951
951
|
try {
|
|
952
952
|
return JSON.parse(fs2.readFileSync(path2.join(__dirname, "..", "..", "package.json"), "utf8")).version || "unknown";
|
|
953
953
|
} catch {
|
|
@@ -4639,23 +4639,66 @@ var require_desktop = __commonJS({
|
|
|
4639
4639
|
"src/platform/os/desktop.js"(exports2, module2) {
|
|
4640
4640
|
"use strict";
|
|
4641
4641
|
var fs2 = require("node:fs");
|
|
4642
|
+
var os2 = require("node:os");
|
|
4643
|
+
var path2 = require("node:path");
|
|
4642
4644
|
var PLATFORM = process.platform;
|
|
4643
|
-
|
|
4645
|
+
var X11_DIR = "/tmp/.X11-unix";
|
|
4646
|
+
function deps(o) {
|
|
4647
|
+
const ov = o || {};
|
|
4648
|
+
return {
|
|
4649
|
+
env: ov.env || process.env,
|
|
4650
|
+
readdir: ov.readdir || ((p) => fs2.readdirSync(p)),
|
|
4651
|
+
exists: ov.exists || ((p) => fs2.existsSync(p)),
|
|
4652
|
+
home: ov.home || os2.homedir(),
|
|
4653
|
+
uid: typeof process.getuid === "function" ? process.getuid() : 0
|
|
4654
|
+
};
|
|
4655
|
+
}
|
|
4656
|
+
function runtimeDir(env, uid) {
|
|
4657
|
+
return env.XDG_RUNTIME_DIR || "/run/user/" + uid;
|
|
4658
|
+
}
|
|
4659
|
+
function x11Displays(o) {
|
|
4660
|
+
const d = deps(o);
|
|
4644
4661
|
try {
|
|
4645
|
-
return
|
|
4662
|
+
return d.readdir(X11_DIR).filter((f) => /^X\d+$/.test(f)).map((f) => Number(f.slice(1))).sort((a, b) => a - b);
|
|
4646
4663
|
} catch {
|
|
4647
|
-
return
|
|
4664
|
+
return [];
|
|
4648
4665
|
}
|
|
4649
4666
|
}
|
|
4650
|
-
function
|
|
4651
|
-
const
|
|
4652
|
-
const rt = process.env.XDG_RUNTIME_DIR || "/run/user/" + uid;
|
|
4667
|
+
function waylandSockets(o) {
|
|
4668
|
+
const d = deps(o);
|
|
4653
4669
|
try {
|
|
4654
|
-
return
|
|
4670
|
+
return d.readdir(runtimeDir(d.env, d.uid)).filter((f) => /^wayland-\d+$/.test(f)).sort();
|
|
4655
4671
|
} catch {
|
|
4656
|
-
return
|
|
4672
|
+
return [];
|
|
4657
4673
|
}
|
|
4658
4674
|
}
|
|
4675
|
+
function hasX11Socket(o) {
|
|
4676
|
+
return x11Displays(o).length > 0;
|
|
4677
|
+
}
|
|
4678
|
+
function hasWaylandSocket(o) {
|
|
4679
|
+
return waylandSockets(o).length > 0;
|
|
4680
|
+
}
|
|
4681
|
+
function sessionEnv(o) {
|
|
4682
|
+
const d = deps(o);
|
|
4683
|
+
const out = {};
|
|
4684
|
+
if (PLATFORM !== "linux") return out;
|
|
4685
|
+
if (!d.env.DISPLAY && !d.env.WAYLAND_DISPLAY) {
|
|
4686
|
+
const xs = x11Displays(d);
|
|
4687
|
+
if (xs.length) {
|
|
4688
|
+
out.DISPLAY = ":" + xs[0];
|
|
4689
|
+
const xauth = path2.join(d.home, ".Xauthority");
|
|
4690
|
+
if (d.exists(xauth)) out.XAUTHORITY = xauth;
|
|
4691
|
+
} else {
|
|
4692
|
+
const wl = waylandSockets(d);
|
|
4693
|
+
if (wl.length) out.WAYLAND_DISPLAY = wl[0];
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4696
|
+
if (!d.env.DBUS_SESSION_BUS_ADDRESS) {
|
|
4697
|
+
const bus = path2.join(runtimeDir(d.env, d.uid), "bus");
|
|
4698
|
+
if (d.exists(bus)) out.DBUS_SESSION_BUS_ADDRESS = "unix:path=" + bus;
|
|
4699
|
+
}
|
|
4700
|
+
return out;
|
|
4701
|
+
}
|
|
4659
4702
|
function sessionAvailable() {
|
|
4660
4703
|
if (PLATFORM === "linux") {
|
|
4661
4704
|
if (process.env.DISPLAY || process.env.WAYLAND_DISPLAY) return true;
|
|
@@ -4682,7 +4725,7 @@ var require_desktop = __commonJS({
|
|
|
4682
4725
|
reason: "session-scoped-by-launcher"
|
|
4683
4726
|
};
|
|
4684
4727
|
}
|
|
4685
|
-
module2.exports = { sessionAvailable, describe, PLATFORM };
|
|
4728
|
+
module2.exports = { sessionAvailable, sessionEnv, describe, x11Displays, waylandSockets, PLATFORM };
|
|
4686
4729
|
}
|
|
4687
4730
|
});
|
|
4688
4731
|
|
|
@@ -4755,8 +4798,9 @@ var require_capability_profile = __commonJS({
|
|
|
4755
4798
|
autostart: true,
|
|
4756
4799
|
// 期望 schtasks(实测覆写)
|
|
4757
4800
|
frpExpose: true,
|
|
4758
|
-
// 可打开,但
|
|
4759
|
-
//
|
|
4801
|
+
// 可打开,但 Windows 没有可信调度器(系统调度器只有 darwin 的 open 与 linux 的 xdg-open),
|
|
4802
|
+
// 只能直启探测层解析出的浏览器本体;浏览器已在运行时本次进程只转交地址,退出码与窗口出现与否无关,
|
|
4803
|
+
// 故该平台每次调用最多到 handedOff(判据见 browser.js#ownsItsWindow)。能力位只声明「能交出去」。
|
|
4760
4804
|
openBrowser: true,
|
|
4761
4805
|
hostService: "windows-service",
|
|
4762
4806
|
guardAutostart: true,
|
|
@@ -5452,18 +5496,567 @@ var require_notify = __commonJS({
|
|
|
5452
5496
|
}
|
|
5453
5497
|
});
|
|
5454
5498
|
|
|
5499
|
+
// src/platform/os/browser-inventory.js
|
|
5500
|
+
var require_browser_inventory = __commonJS({
|
|
5501
|
+
"src/platform/os/browser-inventory.js"(exports2, module2) {
|
|
5502
|
+
"use strict";
|
|
5503
|
+
var fs2 = require("node:fs");
|
|
5504
|
+
var path2 = require("node:path");
|
|
5505
|
+
var os2 = require("node:os");
|
|
5506
|
+
var exec = require_exec();
|
|
5507
|
+
var { isExecutableFile } = require_exec_path();
|
|
5508
|
+
var PROBE_TIMEOUT_MS = 1500;
|
|
5509
|
+
function engineOf(bin) {
|
|
5510
|
+
const base = String(bin || "").toLowerCase().split(/[\\/]/).pop();
|
|
5511
|
+
if (/(chrome|chromium|msedge|edge|brave|vivaldi|opera|thorium)/.test(base)) return "chromium";
|
|
5512
|
+
if (/(firefox|librewolf|waterfox)/.test(base)) return "firefox";
|
|
5513
|
+
return "other";
|
|
5514
|
+
}
|
|
5515
|
+
function tokenizeExec(line) {
|
|
5516
|
+
const toks = [];
|
|
5517
|
+
let cur = "";
|
|
5518
|
+
let q = null;
|
|
5519
|
+
let esc = false;
|
|
5520
|
+
let has = false;
|
|
5521
|
+
for (const ch of String(line)) {
|
|
5522
|
+
if (esc) {
|
|
5523
|
+
cur += ch;
|
|
5524
|
+
esc = false;
|
|
5525
|
+
continue;
|
|
5526
|
+
}
|
|
5527
|
+
if (ch === "\\") {
|
|
5528
|
+
esc = true;
|
|
5529
|
+
has = true;
|
|
5530
|
+
continue;
|
|
5531
|
+
}
|
|
5532
|
+
if (q) {
|
|
5533
|
+
if (ch === q) q = null;
|
|
5534
|
+
else cur += ch;
|
|
5535
|
+
continue;
|
|
5536
|
+
}
|
|
5537
|
+
if (ch === "'" || ch === '"') {
|
|
5538
|
+
q = ch;
|
|
5539
|
+
has = true;
|
|
5540
|
+
continue;
|
|
5541
|
+
}
|
|
5542
|
+
if (/\s/.test(ch)) {
|
|
5543
|
+
if (has) {
|
|
5544
|
+
toks.push(cur);
|
|
5545
|
+
cur = "";
|
|
5546
|
+
has = false;
|
|
5547
|
+
}
|
|
5548
|
+
continue;
|
|
5549
|
+
}
|
|
5550
|
+
cur += ch;
|
|
5551
|
+
has = true;
|
|
5552
|
+
}
|
|
5553
|
+
if (has) toks.push(cur);
|
|
5554
|
+
return toks;
|
|
5555
|
+
}
|
|
5556
|
+
function parseExecLine(line) {
|
|
5557
|
+
let toks = tokenizeExec(line).filter((t) => t !== "%%" && !/^%[a-zA-Z]$/.test(t));
|
|
5558
|
+
if (toks[0] === "env") {
|
|
5559
|
+
let i = 1;
|
|
5560
|
+
while (i < toks.length && /=/.test(toks[i])) i++;
|
|
5561
|
+
toks = toks.slice(i);
|
|
5562
|
+
}
|
|
5563
|
+
if (!toks.length) return null;
|
|
5564
|
+
return { bin: toks[0], baseArgs: toks.slice(1) };
|
|
5565
|
+
}
|
|
5566
|
+
function regValueOf(out) {
|
|
5567
|
+
const m = String(out || "").match(/REG_(?:EXPAND_SZ|SZ)\s+(.*)/);
|
|
5568
|
+
if (!m) return null;
|
|
5569
|
+
return m[1].trim() || null;
|
|
5570
|
+
}
|
|
5571
|
+
function expandEnvVars(value, env) {
|
|
5572
|
+
const e = env || process.env;
|
|
5573
|
+
return String(value).replace(/%([^%]+)%/g, (all, name) => e[name] === void 0 ? all : e[name]);
|
|
5574
|
+
}
|
|
5575
|
+
function exeFromCmdLine(cmdLine) {
|
|
5576
|
+
const s = String(cmdLine || "");
|
|
5577
|
+
let m = s.match(/^\s*"([^"]+\.exe)"/i);
|
|
5578
|
+
if (m) return m[1];
|
|
5579
|
+
m = s.match(/^\s*(.*?\.exe)/i);
|
|
5580
|
+
return m ? m[1] : null;
|
|
5581
|
+
}
|
|
5582
|
+
function safeRegKeyPart(s) {
|
|
5583
|
+
return typeof s === "string" && s.length > 0 && s.length <= 200 && /^[\x20-\x7e]+$/.test(s) && !/[;|&`$()<>^"'\r\n]/.test(s);
|
|
5584
|
+
}
|
|
5585
|
+
function regValue(runner, note, key, name) {
|
|
5586
|
+
const args = name ? ["query", key, "/v", name] : ["query", key, "/ve"];
|
|
5587
|
+
const out = runner("reg.exe", args);
|
|
5588
|
+
const v = regValueOf(out);
|
|
5589
|
+
note(name ? key + " /v " + name : key, v ? "ok" : "empty");
|
|
5590
|
+
return v;
|
|
5591
|
+
}
|
|
5592
|
+
var REG_HIVE_ALIAS = { HKLM: "HKEY_LOCAL_MACHINE", HKCU: "HKEY_CURRENT_USER", HKCR: "HKEY_CLASSES_ROOT", HKU: "HKEY_USERS", HKCC: "HKEY_CURRENT_CONFIG" };
|
|
5593
|
+
function regKeyFull(key) {
|
|
5594
|
+
const s = String(key || "");
|
|
5595
|
+
const i = s.indexOf("\\");
|
|
5596
|
+
const root = i < 0 ? s : s.slice(0, i);
|
|
5597
|
+
return (REG_HIVE_ALIAS[root.toUpperCase()] || root) + (i < 0 ? "" : s.slice(i));
|
|
5598
|
+
}
|
|
5599
|
+
function regSubkeys(runner, note, key) {
|
|
5600
|
+
const out = runner("reg.exe", ["query", key]);
|
|
5601
|
+
if (!out) {
|
|
5602
|
+
note(key, "unreadable");
|
|
5603
|
+
return [];
|
|
5604
|
+
}
|
|
5605
|
+
const prefix = regKeyFull(key) + "\\";
|
|
5606
|
+
const names = [];
|
|
5607
|
+
for (const line of String(out).split(/\r?\n/)) {
|
|
5608
|
+
const l = line.trim();
|
|
5609
|
+
if (!/^HKEY_/i.test(l) || l.length <= prefix.length) continue;
|
|
5610
|
+
if (l.slice(0, prefix.length).toUpperCase() !== prefix.toUpperCase()) continue;
|
|
5611
|
+
const rest = l.slice(prefix.length);
|
|
5612
|
+
if (rest && !rest.includes("\\") && safeRegKeyPart(rest)) names.push(rest);
|
|
5613
|
+
}
|
|
5614
|
+
note(key, names.length ? names.length + " \u9879" : "\u65E0\u5B50\u952E");
|
|
5615
|
+
return names;
|
|
5616
|
+
}
|
|
5617
|
+
var WIN_APP_PATHS = ["msedge.exe", "chrome.exe", "firefox.exe", "brave.exe", "opera.exe", "vivaldi.exe", "chromium.exe", "thorium.exe", "librewolf.exe"];
|
|
5618
|
+
function winExeOfProgId(runner, note, progId, env) {
|
|
5619
|
+
if (!safeRegKeyPart(progId)) return null;
|
|
5620
|
+
for (const root of ["HKCU\\Software\\Classes", "HKLM\\Software\\Classes"]) {
|
|
5621
|
+
const cmd2 = regValue(runner, note, root + "\\" + progId + "\\shell\\open\\command");
|
|
5622
|
+
const exe = cmd2 ? exeFromCmdLine(expandEnvVars(cmd2, env)) : null;
|
|
5623
|
+
if (exe) return exe;
|
|
5624
|
+
}
|
|
5625
|
+
return null;
|
|
5626
|
+
}
|
|
5627
|
+
function probeWin(d) {
|
|
5628
|
+
const { runOut, env, canExec } = d;
|
|
5629
|
+
const notes = [];
|
|
5630
|
+
const note = (source, detail) => {
|
|
5631
|
+
notes.push({ source, detail });
|
|
5632
|
+
};
|
|
5633
|
+
const found = /* @__PURE__ */ new Map();
|
|
5634
|
+
const keyOf = (exe) => String(exe || "").toLowerCase().replace(/[\\/]/g, "\\");
|
|
5635
|
+
const push = (exe, how) => {
|
|
5636
|
+
const full = expandEnvVars(exe, env).trim();
|
|
5637
|
+
if (!/\.exe$/i.test(full)) {
|
|
5638
|
+
note(how, "\u6765\u6E90\u7ED9\u51FA\u7684\u4E0D\u662F exe \u8DEF\u5F84: " + full);
|
|
5639
|
+
return null;
|
|
5640
|
+
}
|
|
5641
|
+
const k = keyOf(full);
|
|
5642
|
+
const hit = found.get(k);
|
|
5643
|
+
if (hit) {
|
|
5644
|
+
if (!hit.sources.includes(how)) hit.sources.push(how);
|
|
5645
|
+
return hit;
|
|
5646
|
+
}
|
|
5647
|
+
if (!canExec(full)) {
|
|
5648
|
+
note(how, "\u6307\u5411\u7684\u6587\u4EF6\u4E0D\u53EF\u6267\u884C: " + full);
|
|
5649
|
+
return null;
|
|
5650
|
+
}
|
|
5651
|
+
const item = { id: k, name: path2.basename(full).replace(/\.exe$/i, ""), engine: engineOf(full), bin: full, source: how, sources: [how] };
|
|
5652
|
+
found.set(k, item);
|
|
5653
|
+
note(how, item.name);
|
|
5654
|
+
return item;
|
|
5655
|
+
};
|
|
5656
|
+
const progIds = /* @__PURE__ */ new Map();
|
|
5657
|
+
const addProgId = (pid, how) => {
|
|
5658
|
+
const s = String(pid || "").trim();
|
|
5659
|
+
if (!safeRegKeyPart(s)) return;
|
|
5660
|
+
if (progIds.get(s) === "userchoice") return;
|
|
5661
|
+
progIds.set(s, how);
|
|
5662
|
+
};
|
|
5663
|
+
let defaultId = null;
|
|
5664
|
+
let defaultSource = null;
|
|
5665
|
+
const DEF_RANK = { userchoice: 1, "scheme-association": 2, "only-installed": 9 };
|
|
5666
|
+
let defRank = 99;
|
|
5667
|
+
const setDefault = (item, how) => {
|
|
5668
|
+
const r = DEF_RANK[how] === void 0 ? 99 : DEF_RANK[how];
|
|
5669
|
+
if (item && r < defRank) {
|
|
5670
|
+
defRank = r;
|
|
5671
|
+
defaultId = item.id;
|
|
5672
|
+
defaultSource = how;
|
|
5673
|
+
}
|
|
5674
|
+
};
|
|
5675
|
+
const cmdToExe = (raw) => raw ? exeFromCmdLine(expandEnvVars(raw, env)) : null;
|
|
5676
|
+
const uc = regValue(runOut, note, "HKCU\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\https\\UserChoice", "ProgId");
|
|
5677
|
+
if (uc) addProgId(uc, "userchoice");
|
|
5678
|
+
for (const root of ["HKCU\\Software\\Classes", "HKLM\\Software\\Classes"]) {
|
|
5679
|
+
const pid = regValue(runOut, note, root + "\\https");
|
|
5680
|
+
if (pid) addProgId(pid, "scheme-association");
|
|
5681
|
+
const exe = cmdToExe(regValue(runOut, note, root + "\\https\\shell\\open\\command"));
|
|
5682
|
+
if (exe) setDefault(push(exe, "scheme-association"), "scheme-association");
|
|
5683
|
+
}
|
|
5684
|
+
for (const name of regSubkeys(runOut, note, "HKLM\\SOFTWARE\\Clients\\StartMenuInternet")) {
|
|
5685
|
+
addProgId(name, "startmenu-catalog");
|
|
5686
|
+
const exe = cmdToExe(regValue(runOut, note, "HKLM\\SOFTWARE\\Clients\\StartMenuInternet\\" + name + "\\shell\\open\\command")) || winExeOfProgId(runOut, note, name, env);
|
|
5687
|
+
if (exe) push(exe, "startmenu-catalog");
|
|
5688
|
+
}
|
|
5689
|
+
for (const root of ["HKLM\\SOFTWARE", "HKCU\\SOFTWARE"]) {
|
|
5690
|
+
for (const capPath of regValueTargets(runOut, note, root + "\\RegisteredApplications")) {
|
|
5691
|
+
const https = regValue(runOut, note, capPath + "\\UrlAssociations\\https");
|
|
5692
|
+
const sid = regValue(runOut, note, capPath, "StartMenuInternet");
|
|
5693
|
+
const pid = https || sid;
|
|
5694
|
+
if (pid) addProgId(pid, "registered-apps");
|
|
5695
|
+
}
|
|
5696
|
+
}
|
|
5697
|
+
for (const exe of WIN_APP_PATHS) {
|
|
5698
|
+
for (const root of ["HKCU", "HKLM"]) {
|
|
5699
|
+
const v = regValue(runOut, note, root + "\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" + exe);
|
|
5700
|
+
if (v && push(v, "app-paths")) break;
|
|
5701
|
+
}
|
|
5702
|
+
}
|
|
5703
|
+
for (const [pid, how] of progIds) {
|
|
5704
|
+
const exe = winExeOfProgId(runOut, note, pid, env);
|
|
5705
|
+
if (!exe) continue;
|
|
5706
|
+
const item = push(exe, how);
|
|
5707
|
+
if (how === "userchoice") setDefault(item, "userchoice");
|
|
5708
|
+
}
|
|
5709
|
+
if (found.size === 1) setDefault([...found.values()][0], "only-installed");
|
|
5710
|
+
return { browsers: [...found.values()], defaultId, defaultSource, probed: notes };
|
|
5711
|
+
}
|
|
5712
|
+
function regValueTargets(runOut, note, key) {
|
|
5713
|
+
const out = runOut("reg.exe", ["query", key]);
|
|
5714
|
+
if (!out) {
|
|
5715
|
+
note(key, "unreadable");
|
|
5716
|
+
return [];
|
|
5717
|
+
}
|
|
5718
|
+
const paths = [];
|
|
5719
|
+
for (const line of String(out).split(/\r?\n/)) {
|
|
5720
|
+
const m = line.trim().match(/REG_SZ\s+(.*)/);
|
|
5721
|
+
if (!m) continue;
|
|
5722
|
+
const rel = m[1].trim();
|
|
5723
|
+
if (!safeRegKeyPart(rel)) continue;
|
|
5724
|
+
const root = key.slice(0, key.indexOf("\\"));
|
|
5725
|
+
paths.push(root + "\\" + rel);
|
|
5726
|
+
}
|
|
5727
|
+
note(key, paths.length ? paths.length + " \u4E2A\u80FD\u529B\u8DEF\u5F84" : "\u65E0\u503C");
|
|
5728
|
+
return paths;
|
|
5729
|
+
}
|
|
5730
|
+
var MAC_JXA_LIST = [
|
|
5731
|
+
"ObjC.import('Foundation');",
|
|
5732
|
+
"var ws=$.NSWorkspace.sharedWorkspace;",
|
|
5733
|
+
"var u=$.NSURL.URLWithString('https://dsh.local/probe');",
|
|
5734
|
+
"var out=[];var def='';",
|
|
5735
|
+
"try{var d=ws.URLForApplicationToOpenURL(u); if(!d.isNil()) def=ObjC.unwrap(d.path)||'';}catch(e){}",
|
|
5736
|
+
"var list=null;",
|
|
5737
|
+
"try{list=ws.urlsForApplicationsToOpenURL(u);}catch(e){}",
|
|
5738
|
+
"if(list===null||typeof list.count!=='number'){if(def){out.push(def+'\\t\\t1');}}else{",
|
|
5739
|
+
"var n=Number(list.count);",
|
|
5740
|
+
"for(var i=0;i<n;i++){",
|
|
5741
|
+
"var p=ObjC.unwrap(list.objectAtIndex(i).path)||''; if(!p) continue;",
|
|
5742
|
+
"var exe='';var bid='';",
|
|
5743
|
+
"var b=$.NSBundle.bundleWithPath(p);",
|
|
5744
|
+
"if(!b.isNil()){exe=ObjC.unwrap(b.executablePath)||'';bid=ObjC.unwrap(b.bundleIdentifier)||'';}",
|
|
5745
|
+
"out.push((exe||p)+'\\t'+bid+'\\t'+(p&&def&&p===def?1:0));}",
|
|
5746
|
+
"}",
|
|
5747
|
+
// 末句必须是裸表达式:osascript 取的是最后一条**语句**的值,if/else 语句不产结果,
|
|
5748
|
+
// 写在分支里会让整段查询输出空字符串(表现为「系统未报任何可用应用」)。
|
|
5749
|
+
"out.join('\\n');"
|
|
5750
|
+
].join("");
|
|
5751
|
+
function probeMac(d) {
|
|
5752
|
+
const { runOut, canExec } = d;
|
|
5753
|
+
const notes = [];
|
|
5754
|
+
const note = (source, detail) => {
|
|
5755
|
+
notes.push({ source, detail });
|
|
5756
|
+
};
|
|
5757
|
+
const out = runOut("osascript", ["-l", "JavaScript", "-e", MAC_JXA_LIST]);
|
|
5758
|
+
if (!out || !out.trim()) {
|
|
5759
|
+
note("launchservices", "\u67E5\u8BE2\u65E0\u8F93\u51FA\uFF08\u65E7\u7CFB\u7EDF\u6216\u88AB\u6743\u9650\u62E6\u622A\uFF09");
|
|
5760
|
+
return { browsers: [], defaultId: null, defaultSource: null, probed: notes };
|
|
5761
|
+
}
|
|
5762
|
+
const keyOf = (exe) => String(exe || "").toLowerCase();
|
|
5763
|
+
const found = /* @__PURE__ */ new Map();
|
|
5764
|
+
let defaultId = null;
|
|
5765
|
+
let defaultSource = null;
|
|
5766
|
+
for (const line of out.trim().split("\n")) {
|
|
5767
|
+
const parts = line.split(" ");
|
|
5768
|
+
const bin = (parts[0] || "").trim();
|
|
5769
|
+
if (!bin) continue;
|
|
5770
|
+
if (!canExec(bin)) {
|
|
5771
|
+
note("launchservices", "\u4E0D\u53EF\u6267\u884C: " + bin);
|
|
5772
|
+
continue;
|
|
5773
|
+
}
|
|
5774
|
+
const k = keyOf(bin);
|
|
5775
|
+
if (!found.has(k)) found.set(k, { id: k, name: path2.basename(bin), engine: engineOf(bin), bin, source: "launchservices", sources: ["launchservices"], isDefault: false });
|
|
5776
|
+
if (parts[2] === "1") {
|
|
5777
|
+
found.get(k).isDefault = true;
|
|
5778
|
+
if (!defaultId) {
|
|
5779
|
+
defaultId = k;
|
|
5780
|
+
defaultSource = "launchservices";
|
|
5781
|
+
}
|
|
5782
|
+
}
|
|
5783
|
+
}
|
|
5784
|
+
note("launchservices", found.size ? found.size + " \u4E2A\u53EF\u6253\u5F00 https \u7684\u5E94\u7528" : "\u7CFB\u7EDF\u672A\u62A5\u4EFB\u4F55\u53EF\u7528\u5E94\u7528");
|
|
5785
|
+
if (!defaultId && found.size === 1) {
|
|
5786
|
+
defaultId = [...found.keys()][0];
|
|
5787
|
+
defaultSource = "only-installed";
|
|
5788
|
+
}
|
|
5789
|
+
return { browsers: [...found.values()], defaultId, defaultSource, probed: notes };
|
|
5790
|
+
}
|
|
5791
|
+
var PJ = path2.posix.join;
|
|
5792
|
+
function desktopDirs(env, home) {
|
|
5793
|
+
const dataHome = env.XDG_DATA_HOME || PJ(home, ".local", "share");
|
|
5794
|
+
const dataDirs = String(env.XDG_DATA_DIRS || "/usr/local/share:/usr/share").split(":").filter(Boolean);
|
|
5795
|
+
const dirs = [[dataHome, "xdg"], ...dataDirs.map((p) => [p, "xdg"])];
|
|
5796
|
+
dirs.push([PJ(home, ".local", "share"), "xdg"]);
|
|
5797
|
+
dirs.push(["/var/lib/flatpak/exports/share", "flatpak"]);
|
|
5798
|
+
dirs.push([PJ(home, ".local", "share", "flatpak", "exports", "share"), "flatpak"]);
|
|
5799
|
+
dirs.push(["/var/lib/snapd/desktop", "snap"]);
|
|
5800
|
+
const seen = [];
|
|
5801
|
+
return dirs.map(([root, kind]) => ({ dir: PJ(root, "applications"), kind })).filter((x) => {
|
|
5802
|
+
if (seen.includes(x.dir)) return false;
|
|
5803
|
+
seen.push(x.dir);
|
|
5804
|
+
return true;
|
|
5805
|
+
});
|
|
5806
|
+
}
|
|
5807
|
+
function browserFromDesktop(text, kind, file) {
|
|
5808
|
+
let inMain = false;
|
|
5809
|
+
const got = {};
|
|
5810
|
+
for (const line of String(text).split(/\r?\n/)) {
|
|
5811
|
+
if (/^\[Desktop Entry\]\s*$/.test(line)) {
|
|
5812
|
+
inMain = true;
|
|
5813
|
+
continue;
|
|
5814
|
+
}
|
|
5815
|
+
if (/^\[/.test(line)) break;
|
|
5816
|
+
if (!inMain) continue;
|
|
5817
|
+
const m = line.match(/^(Exec|Name|TryExec|Categories)=(.*)$/);
|
|
5818
|
+
if (!m) continue;
|
|
5819
|
+
if (m[1] === "Name" && got.Name) continue;
|
|
5820
|
+
got[m[1]] = m[2].trim();
|
|
5821
|
+
}
|
|
5822
|
+
if (!got.Exec) return null;
|
|
5823
|
+
const categories = String(got.Categories || "");
|
|
5824
|
+
const parsed = parseExecLine(got.Exec);
|
|
5825
|
+
if (!parsed) return null;
|
|
5826
|
+
const engine = engineOf(parsed.bin);
|
|
5827
|
+
const claimsBrowser = /(^|;)WebBrowser(;|$)/.test(categories);
|
|
5828
|
+
if (!claimsBrowser && engine === "other") return null;
|
|
5829
|
+
if (engine === "other") return null;
|
|
5830
|
+
return {
|
|
5831
|
+
// id 恒为归一后的可执行文件路径:defaultId 靠它在清单里定位条目,三平台同一契约
|
|
5832
|
+
id: parsed.bin.toLowerCase(),
|
|
5833
|
+
name: got.Name || path2.basename(file, ".desktop"),
|
|
5834
|
+
engine,
|
|
5835
|
+
bin: parsed.bin,
|
|
5836
|
+
baseArgs: parsed.baseArgs,
|
|
5837
|
+
source: kind,
|
|
5838
|
+
desktopFile: file
|
|
5839
|
+
};
|
|
5840
|
+
}
|
|
5841
|
+
function resolveLinuxBin(bin, canExec, env) {
|
|
5842
|
+
const b = String(bin || "").trim();
|
|
5843
|
+
if (!b) return null;
|
|
5844
|
+
if (b.startsWith("/")) return canExec(b) ? b : null;
|
|
5845
|
+
if (b.includes("/")) return null;
|
|
5846
|
+
for (const dir of String(env.PATH || "").split(":")) {
|
|
5847
|
+
if (!dir) continue;
|
|
5848
|
+
const p = PJ(dir.replace(/\/+$/, ""), b);
|
|
5849
|
+
if (canExec(p)) return p;
|
|
5850
|
+
}
|
|
5851
|
+
return null;
|
|
5852
|
+
}
|
|
5853
|
+
function probeLinux(d) {
|
|
5854
|
+
const { runOut, readFile, exists, listDir, canExec, env, home } = d;
|
|
5855
|
+
const notes = [];
|
|
5856
|
+
const note = (source, detail) => {
|
|
5857
|
+
notes.push({ source, detail });
|
|
5858
|
+
};
|
|
5859
|
+
const found = /* @__PURE__ */ new Map();
|
|
5860
|
+
const usable = (item) => {
|
|
5861
|
+
const resolved = resolveLinuxBin(item.bin, canExec, env);
|
|
5862
|
+
if (!resolved) {
|
|
5863
|
+
note(item.source, "\u4E0D\u53EF\u6267\u884C: " + item.bin);
|
|
5864
|
+
return null;
|
|
5865
|
+
}
|
|
5866
|
+
const k = resolved.toLowerCase();
|
|
5867
|
+
const hit = found.get(k);
|
|
5868
|
+
if (hit) {
|
|
5869
|
+
if (!hit.sources.includes(item.source)) hit.sources.push(item.source);
|
|
5870
|
+
return hit;
|
|
5871
|
+
}
|
|
5872
|
+
const v = Object.assign({}, item, { id: k, bin: resolved, sources: [item.source] });
|
|
5873
|
+
found.set(k, v);
|
|
5874
|
+
return v;
|
|
5875
|
+
};
|
|
5876
|
+
for (const { dir, kind } of desktopDirs(env, home)) {
|
|
5877
|
+
let names = [];
|
|
5878
|
+
try {
|
|
5879
|
+
names = listDir(dir).filter((f) => f.endsWith(".desktop"));
|
|
5880
|
+
} catch {
|
|
5881
|
+
continue;
|
|
5882
|
+
}
|
|
5883
|
+
for (const f of names) {
|
|
5884
|
+
let text = null;
|
|
5885
|
+
try {
|
|
5886
|
+
text = readFile(PJ(dir, f));
|
|
5887
|
+
} catch {
|
|
5888
|
+
continue;
|
|
5889
|
+
}
|
|
5890
|
+
const item = browserFromDesktop(text, kind, f);
|
|
5891
|
+
if (item) usable(item);
|
|
5892
|
+
}
|
|
5893
|
+
}
|
|
5894
|
+
let defaultId = null;
|
|
5895
|
+
let defaultSource = null;
|
|
5896
|
+
const fromMime = linuxDefaultFromMimeApps(readFile, exists, env, home, note);
|
|
5897
|
+
if (fromMime) {
|
|
5898
|
+
const item = usable(fromMime);
|
|
5899
|
+
if (item) {
|
|
5900
|
+
defaultId = item.id;
|
|
5901
|
+
defaultSource = "mimeapps";
|
|
5902
|
+
}
|
|
5903
|
+
}
|
|
5904
|
+
const id = runOut("xdg-settings", ["get", "default-web-browser"]);
|
|
5905
|
+
const desktopId = id && String(id).trim();
|
|
5906
|
+
if (!defaultId && desktopId && /^[A-Za-z0-9._-]+\.desktop$/.test(desktopId)) {
|
|
5907
|
+
for (const { dir } of desktopDirs(env, home)) {
|
|
5908
|
+
const p = PJ(dir, desktopId);
|
|
5909
|
+
let text = null;
|
|
5910
|
+
try {
|
|
5911
|
+
if (exists(p)) text = readFile(p);
|
|
5912
|
+
} catch {
|
|
5913
|
+
continue;
|
|
5914
|
+
}
|
|
5915
|
+
if (text === null) continue;
|
|
5916
|
+
const item = browserFromDesktop(text, "xdg-settings", desktopId);
|
|
5917
|
+
const used = item && usable(item);
|
|
5918
|
+
if (used) {
|
|
5919
|
+
defaultId = used.id;
|
|
5920
|
+
defaultSource = "xdg-settings";
|
|
5921
|
+
break;
|
|
5922
|
+
}
|
|
5923
|
+
}
|
|
5924
|
+
}
|
|
5925
|
+
if (!desktopId) note("xdg-settings", "\u65E0\u8F93\u51FA");
|
|
5926
|
+
else if (defaultSource === "xdg-settings") note("xdg-settings", "\u9ED8\u8BA4=" + defaultId);
|
|
5927
|
+
else note("xdg-settings", "\u62A5\u51FA " + desktopId + (defaultId ? "\uFF08\u9ED8\u8BA4\u5DF2\u7531 " + defaultSource + " \u5B9A\u51FA\uFF09" : " \u4F46\u4E0D\u53EF\u7528"));
|
|
5928
|
+
if (!defaultId && found.size === 1) {
|
|
5929
|
+
defaultId = [...found.keys()][0];
|
|
5930
|
+
defaultSource = "only-installed";
|
|
5931
|
+
}
|
|
5932
|
+
return { browsers: [...found.values()], defaultId, defaultSource, probed: notes };
|
|
5933
|
+
}
|
|
5934
|
+
function linuxDefaultFromMimeApps(readFile, exists, env, home, note) {
|
|
5935
|
+
const cfgHome = env.XDG_CONFIG_HOME || PJ(home, ".config");
|
|
5936
|
+
const cfgDirs = String(env.XDG_CONFIG_DIRS || "/etc/xdg").split(":").filter(Boolean);
|
|
5937
|
+
const dataDirs = String(env.XDG_DATA_DIRS || "/usr/local/share:/usr/share").split(":").filter(Boolean);
|
|
5938
|
+
const files = [
|
|
5939
|
+
PJ(cfgHome, "mimeapps.list"),
|
|
5940
|
+
...cfgDirs.map((d) => PJ(d, "mimeapps.list")),
|
|
5941
|
+
...dataDirs.map((d) => PJ(d, "applications", "mimeapps.list"))
|
|
5942
|
+
];
|
|
5943
|
+
for (const f of files) {
|
|
5944
|
+
if (!exists(f)) continue;
|
|
5945
|
+
let text = null;
|
|
5946
|
+
try {
|
|
5947
|
+
text = readFile(f);
|
|
5948
|
+
} catch {
|
|
5949
|
+
continue;
|
|
5950
|
+
}
|
|
5951
|
+
const id = mimeAppsDefault(text);
|
|
5952
|
+
if (!id) continue;
|
|
5953
|
+
note("mimeapps", path2.basename(f) + " -> " + id);
|
|
5954
|
+
for (const { dir, kind } of desktopDirs(env, home)) {
|
|
5955
|
+
const p = PJ(dir, id);
|
|
5956
|
+
if (!exists(p)) continue;
|
|
5957
|
+
let dt = null;
|
|
5958
|
+
try {
|
|
5959
|
+
dt = readFile(p);
|
|
5960
|
+
} catch {
|
|
5961
|
+
continue;
|
|
5962
|
+
}
|
|
5963
|
+
const item = browserFromDesktop(dt, kind, id);
|
|
5964
|
+
if (item) return item;
|
|
5965
|
+
}
|
|
5966
|
+
return null;
|
|
5967
|
+
}
|
|
5968
|
+
note("mimeapps", "\u65E0\u9ED8\u8BA4\u9879");
|
|
5969
|
+
return null;
|
|
5970
|
+
}
|
|
5971
|
+
function mimeAppsDefault(text) {
|
|
5972
|
+
let inDefault = false;
|
|
5973
|
+
for (const line of String(text || "").split(/\r?\n/)) {
|
|
5974
|
+
if (/^\s*\[/.test(line)) {
|
|
5975
|
+
inDefault = /^\s*\[Default Applications\]\s*$/.test(line);
|
|
5976
|
+
continue;
|
|
5977
|
+
}
|
|
5978
|
+
if (!inDefault) continue;
|
|
5979
|
+
const m = line.match(/^\s*x-scheme-handler\/https?\s*=\s*(.*)$/i);
|
|
5980
|
+
if (!m) continue;
|
|
5981
|
+
const ids = m[1].split(";").map((s) => s.trim()).filter((s) => /^[A-Za-z0-9._-]+\.desktop$/.test(s));
|
|
5982
|
+
if (ids.length) return ids[0];
|
|
5983
|
+
}
|
|
5984
|
+
return null;
|
|
5985
|
+
}
|
|
5986
|
+
function probe(platform, d) {
|
|
5987
|
+
const pl = platform || process.platform;
|
|
5988
|
+
const dd = Object.assign({}, d, { canExec: d.canExec || ((p) => isExecutableFile(p, pl)) });
|
|
5989
|
+
if (pl === "win32") return probeWin(dd);
|
|
5990
|
+
if (pl === "darwin") return probeMac(dd);
|
|
5991
|
+
return probeLinux(dd);
|
|
5992
|
+
}
|
|
5993
|
+
var CACHE = /* @__PURE__ */ Object.create(null);
|
|
5994
|
+
function inventory(platform, o) {
|
|
5995
|
+
const ov = o || {};
|
|
5996
|
+
const pl = platform || process.platform;
|
|
5997
|
+
const now = ov.now || (() => Date.now());
|
|
5998
|
+
const ttl = ov.ttlMs === void 0 ? 6e4 : ov.ttlMs;
|
|
5999
|
+
const cached = CACHE[pl];
|
|
6000
|
+
if (!ov.force && cached && now() - cached.at < ttl) return Object.assign({ cached: true }, cached.value);
|
|
6001
|
+
const runOut = ov.runOut || ((bin, args) => exec.runOut(bin, args, { timeoutMs: PROBE_TIMEOUT_MS }));
|
|
6002
|
+
const readFile = ov.readFile || ((p) => fs2.readFileSync(p, "utf8"));
|
|
6003
|
+
const exists = ov.exists || ((p) => fs2.existsSync(p));
|
|
6004
|
+
const listDir = ov.listDir || ((p) => fs2.readdirSync(p));
|
|
6005
|
+
let value;
|
|
6006
|
+
try {
|
|
6007
|
+
value = probe(pl, { runOut, readFile, exists, listDir, canExec: ov.canExec, env: ov.env || process.env, home: ov.home || os2.homedir() });
|
|
6008
|
+
} catch (e) {
|
|
6009
|
+
value = { browsers: [], defaultId: null, defaultSource: null, probed: [{ source: "probe-error", detail: String(e && e.message || e) }] };
|
|
6010
|
+
}
|
|
6011
|
+
value.at = now();
|
|
6012
|
+
value.platform = pl;
|
|
6013
|
+
value.browsers.sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
6014
|
+
CACHE[pl] = { at: now(), value };
|
|
6015
|
+
return Object.assign({ cached: false }, value);
|
|
6016
|
+
}
|
|
6017
|
+
function invalidate(platform) {
|
|
6018
|
+
if (platform) delete CACHE[platform];
|
|
6019
|
+
else for (const k of Object.keys(CACHE)) delete CACHE[k];
|
|
6020
|
+
}
|
|
6021
|
+
module2.exports = {
|
|
6022
|
+
inventory,
|
|
6023
|
+
invalidate,
|
|
6024
|
+
probe,
|
|
6025
|
+
probeWin,
|
|
6026
|
+
probeMac,
|
|
6027
|
+
probeLinux,
|
|
6028
|
+
engineOf,
|
|
6029
|
+
tokenizeExec,
|
|
6030
|
+
parseExecLine,
|
|
6031
|
+
regValueOf,
|
|
6032
|
+
expandEnvVars,
|
|
6033
|
+
exeFromCmdLine,
|
|
6034
|
+
regSubkeys,
|
|
6035
|
+
regKeyFull,
|
|
6036
|
+
regValueTargets,
|
|
6037
|
+
safeRegKeyPart,
|
|
6038
|
+
browserFromDesktop,
|
|
6039
|
+
desktopDirs,
|
|
6040
|
+
resolveLinuxBin,
|
|
6041
|
+
mimeAppsDefault,
|
|
6042
|
+
linuxDefaultFromMimeApps,
|
|
6043
|
+
WIN_APP_PATHS,
|
|
6044
|
+
PROBE_TIMEOUT_MS
|
|
6045
|
+
};
|
|
6046
|
+
}
|
|
6047
|
+
});
|
|
6048
|
+
|
|
5455
6049
|
// src/platform/os/browser.js
|
|
5456
6050
|
var require_browser = __commonJS({
|
|
5457
6051
|
"src/platform/os/browser.js"(exports2, module2) {
|
|
5458
6052
|
"use strict";
|
|
5459
|
-
var fs2 = require("node:fs");
|
|
5460
6053
|
var path2 = require("node:path");
|
|
5461
|
-
var os2 = require("node:os");
|
|
5462
6054
|
var spawnOS = require_spawn();
|
|
5463
6055
|
var desktop = require_desktop();
|
|
5464
6056
|
var CAPABILITY_PROFILES = require_capability_profile();
|
|
5465
6057
|
var { resolveExecutable, isExecutableFile } = require_exec_path();
|
|
5466
|
-
var
|
|
6058
|
+
var detector = require_browser_inventory();
|
|
6059
|
+
var { engineOf } = detector;
|
|
5467
6060
|
function isSafeHttpUrl(url) {
|
|
5468
6061
|
try {
|
|
5469
6062
|
const u = new URL(String(url));
|
|
@@ -5475,7 +6068,7 @@ var require_browser = __commonJS({
|
|
|
5475
6068
|
function openCommand(platform, url) {
|
|
5476
6069
|
const pl = platform || process.platform;
|
|
5477
6070
|
if (pl === "darwin") return { cmd: "open", args: [url] };
|
|
5478
|
-
if (pl === "win32") return
|
|
6071
|
+
if (pl === "win32") return null;
|
|
5479
6072
|
return { cmd: "xdg-open", args: [url] };
|
|
5480
6073
|
}
|
|
5481
6074
|
var SUPPORTED_OPEN_PLATFORMS = Object.keys(CAPABILITY_PROFILES).filter((k) => CAPABILITY_PROFILES[k].openBrowser === true);
|
|
@@ -5499,7 +6092,7 @@ var require_browser = __commonJS({
|
|
|
5499
6092
|
var HANDEDOFF_TEXT = "\u5DF2\u628A\u5730\u5740\u4EA4\u7ED9\u7CFB\u7EDF\uFF0C\u4F46\u8FD9\u6B21\u542F\u52A8\u62FF\u4E0D\u5230\u7A97\u53E3\u662F\u5426\u51FA\u73B0\u7684\u8BC1\u636E";
|
|
5500
6093
|
var FAILURE_TEXT = {
|
|
5501
6094
|
"unsafe-url": "\u5730\u5740\u4E0D\u662F http(s) \u7EDD\u5BF9 URL\uFF0C\u5DF2\u62D2\u7EDD\u4EA4\u7ED9\u6D4F\u89C8\u5668",
|
|
5502
|
-
"no-launcher": "\u672A\
|
|
6095
|
+
"no-launcher": "\u672A\u80FD\u786E\u5B9A\u8BE5\u7528\u54EA\u4E2A\u6D4F\u89C8\u5668\u6253\u5F00\uFF08\u7CFB\u7EDF\u91CC\u8BFB\u4E0D\u5230\u9ED8\u8BA4\u6D4F\u89C8\u5668\u8BBE\u7F6E\uFF09\uFF0C\u8BF7\u5728\u7CFB\u7EDF\u8BBE\u7F6E\u91CC\u6307\u5B9A\u9ED8\u8BA4\u6D4F\u89C8\u5668\u6216\u624B\u52A8\u6253\u5F00\u8BE5\u5730\u5740",
|
|
5503
6096
|
"spawn-failed": "\u6D4F\u89C8\u5668\u542F\u52A8\u5931\u8D25\uFF08\u7CFB\u7EDF\u62D2\u7EDD\u4E86\u8BE5\u547D\u4EE4\uFF09",
|
|
5504
6097
|
"exit-nonzero": "\u7CFB\u7EDF\u62D2\u7EDD\u4E86\u8FD9\u4E2A\u5730\u5740\uFF08\u542F\u52A8\u547D\u4EE4\u975E 0 \u9000\u51FA\uFF09\uFF0C\u7A97\u53E3\u672A\u51FA\u73B0",
|
|
5505
6098
|
"killed-by-signal": "\u6D4F\u89C8\u5668\u542F\u52A8\u547D\u4EE4\u88AB\u7CFB\u7EDF\u7EC8\u6B62\uFF0C\u7A97\u53E3\u672A\u51FA\u73B0",
|
|
@@ -5510,16 +6103,44 @@ var require_browser = __commonJS({
|
|
|
5510
6103
|
if (via !== "dispatcher") return false;
|
|
5511
6104
|
return platform !== "win32";
|
|
5512
6105
|
}
|
|
6106
|
+
function pickLauncher(platform, inv) {
|
|
6107
|
+
const list = inv && Array.isArray(inv.browsers) ? inv.browsers : [];
|
|
6108
|
+
const id = inv && inv.defaultId;
|
|
6109
|
+
const hit = id ? list.find((b) => b.id === id) : null;
|
|
6110
|
+
if (hit) return { browser: hit, how: inv && inv.defaultSource || "default" };
|
|
6111
|
+
if (list.length === 1) return { browser: list[0], how: "only-installed" };
|
|
6112
|
+
return { browser: null, how: list.length ? "no-default" : "none-found" };
|
|
6113
|
+
}
|
|
6114
|
+
function formOfBin(pl, b) {
|
|
6115
|
+
const engine = b && b.bin ? engineOf(b.bin) : "other";
|
|
6116
|
+
return { engine, direct: !!b && (engine !== "other" || pl === "win32") };
|
|
6117
|
+
}
|
|
5513
6118
|
function openPlan(platform, url, opts) {
|
|
5514
6119
|
const o = opts || {};
|
|
5515
6120
|
const pl = platform || process.platform;
|
|
5516
|
-
const
|
|
5517
|
-
const
|
|
5518
|
-
|
|
5519
|
-
|
|
6121
|
+
const picked = o.pick || pickLauncher(pl, o.inventory);
|
|
6122
|
+
const b = picked.browser;
|
|
6123
|
+
const form = formOfBin(pl, b);
|
|
6124
|
+
if (form.direct) {
|
|
6125
|
+
return {
|
|
6126
|
+
bin: b.bin,
|
|
6127
|
+
engine: form.engine,
|
|
6128
|
+
via: "browser",
|
|
6129
|
+
pick: picked.how,
|
|
6130
|
+
baseArgs: (b.baseArgs || []).concat([url]),
|
|
6131
|
+
exitIsEvidence: ownsItsWindow("browser", pl)
|
|
6132
|
+
};
|
|
5520
6133
|
}
|
|
5521
6134
|
const c = openCommand(pl, url);
|
|
5522
|
-
return { bin:
|
|
6135
|
+
if (!c) return { bin: null, engine: form.engine, via: "none", pick: picked.how, baseArgs: [], exitIsEvidence: false };
|
|
6136
|
+
return {
|
|
6137
|
+
bin: c.cmd,
|
|
6138
|
+
engine: "other",
|
|
6139
|
+
via: "dispatcher",
|
|
6140
|
+
pick: picked.how,
|
|
6141
|
+
baseArgs: c.args,
|
|
6142
|
+
exitIsEvidence: ownsItsWindow("dispatcher", pl)
|
|
6143
|
+
};
|
|
5523
6144
|
}
|
|
5524
6145
|
function observeSpawn(child, windowMs, setTimeoutFn) {
|
|
5525
6146
|
return new Promise((resolve) => {
|
|
@@ -5538,6 +6159,21 @@ var require_browser = __commonJS({
|
|
|
5538
6159
|
});
|
|
5539
6160
|
}
|
|
5540
6161
|
var OPEN_OBSERVE_MS = 1500;
|
|
6162
|
+
function launchDiagnostics(inv, plan, how) {
|
|
6163
|
+
const found = (inv && inv.browsers || []).map((b) => ({
|
|
6164
|
+
name: b.name,
|
|
6165
|
+
engine: b.engine || engineOf(b.bin),
|
|
6166
|
+
via: (b.sources && b.sources.length ? b.sources : [b.source || "unknown"]).join("+")
|
|
6167
|
+
}));
|
|
6168
|
+
return {
|
|
6169
|
+
platform: inv && inv.platform || null,
|
|
6170
|
+
pick: how || plan && plan.pick || "none",
|
|
6171
|
+
bin: plan && plan.bin || null,
|
|
6172
|
+
default: inv && inv.defaultId ? { id: inv.defaultId, source: inv.defaultSource || null } : null,
|
|
6173
|
+
found,
|
|
6174
|
+
probed: inv && inv.probed || []
|
|
6175
|
+
};
|
|
6176
|
+
}
|
|
5541
6177
|
async function openBrowser(url, o) {
|
|
5542
6178
|
const opts = o || {};
|
|
5543
6179
|
const pl = opts.platform || process.platform;
|
|
@@ -5551,16 +6187,27 @@ var require_browser = __commonJS({
|
|
|
5551
6187
|
const spawnWith = typeof opts.spawn === "function" ? opts.spawn : _spawnDetachedIgnored;
|
|
5552
6188
|
const avail = typeof opts.binAvailable === "function" ? opts.binAvailable : binAvailable;
|
|
5553
6189
|
const observe = typeof opts.observe === "function" ? opts.observe : observeSpawn;
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
const
|
|
5559
|
-
|
|
6190
|
+
const resolveInv = typeof opts.resolveInventory === "function" ? opts.resolveInventory : ((platform, deps) => detector.inventory(platform, deps));
|
|
6191
|
+
const inv = "inventory" in opts ? opts.inventory : resolveInv(pl, opts.resolveDeps || {});
|
|
6192
|
+
const plan = openPlan(pl, url, { inventory: inv, pick: opts.pick });
|
|
6193
|
+
const diagnostics = launchDiagnostics(inv, plan, plan.pick);
|
|
6194
|
+
const evidence = {
|
|
6195
|
+
bin: plan.bin,
|
|
6196
|
+
engine: plan.engine,
|
|
6197
|
+
via: plan.via,
|
|
6198
|
+
ownsWindow: plan.exitIsEvidence === true,
|
|
6199
|
+
exitCode: null,
|
|
6200
|
+
exitSignal: null,
|
|
6201
|
+
error: null,
|
|
6202
|
+
diagnostics
|
|
6203
|
+
};
|
|
5560
6204
|
const desktopAvailable = typeof opts.desktopAvailable === "function" ? opts.desktopAvailable : desktop.sessionAvailable;
|
|
5561
6205
|
if (pl === "linux" && !desktopAvailable()) {
|
|
5562
6206
|
return outcome({ ok: false, reason: "no-desktop-session", url, evidence });
|
|
5563
6207
|
}
|
|
6208
|
+
if (!plan.bin) {
|
|
6209
|
+
return outcome({ ok: false, reason: "no-launcher", url, evidence });
|
|
6210
|
+
}
|
|
5564
6211
|
if (!avail(plan.bin)) {
|
|
5565
6212
|
return outcome({ ok: false, reason: "no-launcher", url, evidence });
|
|
5566
6213
|
}
|
|
@@ -5589,6 +6236,28 @@ var require_browser = __commonJS({
|
|
|
5589
6236
|
}
|
|
5590
6237
|
return outcome({ ok: true, confirmed: exitDecides, handedOff: !exitDecides, url, evidence });
|
|
5591
6238
|
}
|
|
6239
|
+
function listBrowsers(o) {
|
|
6240
|
+
const ov = o || {};
|
|
6241
|
+
const inv = detector.inventory(ov.platform, { force: ov.force === true });
|
|
6242
|
+
return {
|
|
6243
|
+
ok: true,
|
|
6244
|
+
platform: inv.platform,
|
|
6245
|
+
cached: inv.cached === true,
|
|
6246
|
+
default: inv.defaultId ? { id: inv.defaultId, source: inv.defaultSource || null } : null,
|
|
6247
|
+
browsers: (inv.browsers || []).map((b) => ({
|
|
6248
|
+
id: b.id,
|
|
6249
|
+
name: b.name,
|
|
6250
|
+
engine: b.engine || engineOf(b.bin),
|
|
6251
|
+
bin: b.bin,
|
|
6252
|
+
sources: b.sources && b.sources.length ? b.sources : [b.source],
|
|
6253
|
+
isDefault: b.id === inv.defaultId
|
|
6254
|
+
})),
|
|
6255
|
+
probed: inv.probed || []
|
|
6256
|
+
};
|
|
6257
|
+
}
|
|
6258
|
+
function invalidateBrowsers(platform) {
|
|
6259
|
+
return detector.invalidate(platform);
|
|
6260
|
+
}
|
|
5592
6261
|
function _spawnDetachedIgnored(bin, args) {
|
|
5593
6262
|
try {
|
|
5594
6263
|
const p = spawnOS.detachedIgnored(bin, args);
|
|
@@ -5618,178 +6287,37 @@ var require_browser = __commonJS({
|
|
|
5618
6287
|
child.unref();
|
|
5619
6288
|
return child;
|
|
5620
6289
|
}
|
|
5621
|
-
function engineOf(bin) {
|
|
5622
|
-
const base = String(bin || "").toLowerCase().split(/[\\/]/).pop();
|
|
5623
|
-
if (/(chrome|chromium|msedge|edge|brave|vivaldi|opera|thorium)/.test(base)) return "chromium";
|
|
5624
|
-
if (/(firefox|librewolf|waterfox)/.test(base)) return "firefox";
|
|
5625
|
-
return "other";
|
|
5626
|
-
}
|
|
5627
|
-
function tokenizeExec(line) {
|
|
5628
|
-
const toks = [];
|
|
5629
|
-
let cur = "";
|
|
5630
|
-
let q = null;
|
|
5631
|
-
let esc = false;
|
|
5632
|
-
let has = false;
|
|
5633
|
-
for (const ch of String(line)) {
|
|
5634
|
-
if (esc) {
|
|
5635
|
-
cur += ch;
|
|
5636
|
-
esc = false;
|
|
5637
|
-
continue;
|
|
5638
|
-
}
|
|
5639
|
-
if (ch === "\\") {
|
|
5640
|
-
esc = true;
|
|
5641
|
-
has = true;
|
|
5642
|
-
continue;
|
|
5643
|
-
}
|
|
5644
|
-
if (q) {
|
|
5645
|
-
if (ch === q) q = null;
|
|
5646
|
-
else cur += ch;
|
|
5647
|
-
continue;
|
|
5648
|
-
}
|
|
5649
|
-
if (ch === "'" || ch === '"') {
|
|
5650
|
-
q = ch;
|
|
5651
|
-
has = true;
|
|
5652
|
-
continue;
|
|
5653
|
-
}
|
|
5654
|
-
if (/\s/.test(ch)) {
|
|
5655
|
-
if (has) {
|
|
5656
|
-
toks.push(cur);
|
|
5657
|
-
cur = "";
|
|
5658
|
-
has = false;
|
|
5659
|
-
}
|
|
5660
|
-
continue;
|
|
5661
|
-
}
|
|
5662
|
-
cur += ch;
|
|
5663
|
-
has = true;
|
|
5664
|
-
}
|
|
5665
|
-
if (has) toks.push(cur);
|
|
5666
|
-
return toks;
|
|
5667
|
-
}
|
|
5668
|
-
function parseExecLine(line) {
|
|
5669
|
-
let toks = tokenizeExec(line).filter((t) => t !== "%%" && !/^%[a-zA-Z]$/.test(t));
|
|
5670
|
-
if (toks[0] === "env") {
|
|
5671
|
-
let i = 1;
|
|
5672
|
-
while (i < toks.length && /=/.test(toks[i])) i++;
|
|
5673
|
-
toks = toks.slice(i);
|
|
5674
|
-
}
|
|
5675
|
-
if (!toks.length) return null;
|
|
5676
|
-
return { bin: toks[0], baseArgs: toks.slice(1) };
|
|
5677
|
-
}
|
|
5678
|
-
function regValueOf(out) {
|
|
5679
|
-
const m = String(out || "").match(/REG_SZ\s+(.*)/);
|
|
5680
|
-
return m ? m[1].trim() : null;
|
|
5681
|
-
}
|
|
5682
|
-
function exeFromCmdLine(cmdLine) {
|
|
5683
|
-
const s = String(cmdLine || "");
|
|
5684
|
-
let m = s.match(/^\s*"([^"]+\.exe)"/i);
|
|
5685
|
-
if (m) return m[1];
|
|
5686
|
-
m = s.match(/^\s*(\S+\.exe)/i);
|
|
5687
|
-
return m ? m[1] : null;
|
|
5688
|
-
}
|
|
5689
|
-
function resolveDefaultWin(runOut) {
|
|
5690
|
-
const roots = ["HKCU\\Software\\Clients\\StartMenuInternet", "HKLM\\Software\\Clients\\StartMenuInternet"];
|
|
5691
|
-
for (const root of roots) {
|
|
5692
|
-
const progId = regValueOf(runOut("reg.exe", ["query", root, "/ve"]));
|
|
5693
|
-
if (!progId || !/^[\x20-\x7e]+$/.test(progId)) continue;
|
|
5694
|
-
for (const r2 of roots) {
|
|
5695
|
-
const cmd2 = regValueOf(runOut("reg.exe", ["query", r2 + "\\" + progId + "\\shell\\open\\command", "/ve"]));
|
|
5696
|
-
const bin = exeFromCmdLine(cmd2);
|
|
5697
|
-
if (bin) return { bin, baseArgs: [] };
|
|
5698
|
-
}
|
|
5699
|
-
}
|
|
5700
|
-
return null;
|
|
5701
|
-
}
|
|
5702
|
-
var MAC_JXA = [
|
|
5703
|
-
"ObjC.import('CoreServices');ObjC.import('Foundation');",
|
|
5704
|
-
"var b=ObjC.unwrap($.LSCopyDefaultHandlerForURLScheme(null,'https'))||ObjC.unwrap($.LSCopyDefaultHandlerForURLScheme(null,'http'));",
|
|
5705
|
-
"if(!b){'EMPTY';}else{",
|
|
5706
|
-
"var u=$.NSWorkspace.workspace.URLForApplicationWithBundleIdentifier(b);",
|
|
5707
|
-
"if(u.isNil()){'EMPTY';}else{",
|
|
5708
|
-
"var e=ObjC.unwrap($.NSBundle.bundleWithURL(u).objectForInfoDictionaryKey('CFBundleExecutable'));",
|
|
5709
|
-
"b+'\\t'+ObjC.unwrap(u.path)+'\\t'+e;}}"
|
|
5710
|
-
].join("");
|
|
5711
|
-
function resolveDefaultMac(runOut) {
|
|
5712
|
-
const out = runOut("osascript", ["-l", "JavaScript", "-e", MAC_JXA]);
|
|
5713
|
-
if (!out) return null;
|
|
5714
|
-
const parts = out.trim().split(" ");
|
|
5715
|
-
if (parts.length < 3 || parts[0] === "EMPTY" || !parts[2]) return null;
|
|
5716
|
-
return { bin: path2.posix.join(parts[1], "Contents", "MacOS", parts[2]), baseArgs: [], bundleId: parts[0] };
|
|
5717
|
-
}
|
|
5718
|
-
function resolveDefaultLinux(runOut, readFile, exists, env, home) {
|
|
5719
|
-
const id = runOut("xdg-settings", ["get", "default-web-browser"]);
|
|
5720
|
-
const desktop2 = id && id.trim();
|
|
5721
|
-
if (!desktop2 || !/^[A-Za-z0-9._-]+\.desktop$/.test(desktop2)) return null;
|
|
5722
|
-
const dirs = [
|
|
5723
|
-
env.XDG_DATA_HOME || path2.join(home, ".local", "share"),
|
|
5724
|
-
"/usr/local/share",
|
|
5725
|
-
"/usr/share",
|
|
5726
|
-
"/var/lib/snapd/desktop"
|
|
5727
|
-
].map((d) => path2.join(d, "applications"));
|
|
5728
|
-
for (const dir of dirs) {
|
|
5729
|
-
const p = path2.join(dir, desktop2);
|
|
5730
|
-
let text = null;
|
|
5731
|
-
try {
|
|
5732
|
-
if (exists(p)) text = readFile(p);
|
|
5733
|
-
} catch {
|
|
5734
|
-
continue;
|
|
5735
|
-
}
|
|
5736
|
-
if (text === null) continue;
|
|
5737
|
-
let inMain = false;
|
|
5738
|
-
for (const line of text.split(/\r?\n/)) {
|
|
5739
|
-
if (/^\[Desktop Entry\]\s*$/.test(line)) {
|
|
5740
|
-
inMain = true;
|
|
5741
|
-
continue;
|
|
5742
|
-
}
|
|
5743
|
-
if (/^\[/.test(line)) break;
|
|
5744
|
-
if (inMain) {
|
|
5745
|
-
const m = line.match(/^Exec=(.+)/);
|
|
5746
|
-
if (m) return parseExecLine(m[1]);
|
|
5747
|
-
}
|
|
5748
|
-
}
|
|
5749
|
-
}
|
|
5750
|
-
return null;
|
|
5751
|
-
}
|
|
5752
|
-
function resolveDefaultBrowser(platform, o) {
|
|
5753
|
-
const ov = o || {};
|
|
5754
|
-
const pl = platform || process.platform;
|
|
5755
|
-
const runOut = ov.runOut || ((bin, args) => exec.runOut(bin, args, { timeoutMs: 5e3 }));
|
|
5756
|
-
const readFile = ov.readFile || ((p) => fs2.readFileSync(p, "utf8"));
|
|
5757
|
-
const exists = ov.exists || ((p) => fs2.existsSync(p));
|
|
5758
|
-
const env = ov.env || process.env;
|
|
5759
|
-
const home = ov.home || os2.homedir();
|
|
5760
|
-
try {
|
|
5761
|
-
if (pl === "win32") return resolveDefaultWin(runOut);
|
|
5762
|
-
if (pl === "darwin") return resolveDefaultMac(runOut);
|
|
5763
|
-
return resolveDefaultLinux(runOut, readFile, exists, env, home);
|
|
5764
|
-
} catch {
|
|
5765
|
-
return null;
|
|
5766
|
-
}
|
|
5767
|
-
}
|
|
5768
6290
|
function isolatedPlan(platform, url, opts) {
|
|
5769
6291
|
const o = opts || {};
|
|
5770
6292
|
const pl = platform || process.platform;
|
|
5771
|
-
const
|
|
5772
|
-
const
|
|
5773
|
-
const
|
|
5774
|
-
|
|
6293
|
+
const picked = o.pick || pickLauncher(pl, o.inventory);
|
|
6294
|
+
const b = picked.browser;
|
|
6295
|
+
const form = formOfBin(pl, b);
|
|
6296
|
+
const baseArgs = b && b.baseArgs || [];
|
|
6297
|
+
if (form.direct && form.engine === "chromium" && o.profileDir) {
|
|
5775
6298
|
const args = ["--incognito", "--user-data-dir=" + o.profileDir];
|
|
5776
6299
|
if (Array.isArray(o.size) && o.size.length === 2) args.push("--window-size=" + o.size[0] + "," + o.size[1]);
|
|
5777
6300
|
if (o.lang) args.push("--lang=" + o.lang);
|
|
5778
6301
|
args.push("--no-first-run", "--no-default-browser-check", "--disable-session-crashed-bubble");
|
|
5779
|
-
return { bin:
|
|
6302
|
+
return { bin: b.bin, args: [...baseArgs, ...args, url], isolated: true, watch: true, envKind: "anti", label: "chromium", pick: picked.how };
|
|
5780
6303
|
}
|
|
5781
|
-
if (engine === "firefox" && o.profileDir) {
|
|
6304
|
+
if (form.direct && form.engine === "firefox" && o.profileDir) {
|
|
5782
6305
|
return {
|
|
5783
|
-
bin:
|
|
6306
|
+
bin: b.bin,
|
|
5784
6307
|
args: [...baseArgs, "--no-remote", "--profile", o.profileDir, "-private-window", url],
|
|
5785
6308
|
isolated: true,
|
|
5786
6309
|
watch: true,
|
|
5787
6310
|
envKind: "anti",
|
|
5788
|
-
label: "firefox"
|
|
6311
|
+
label: "firefox",
|
|
6312
|
+
pick: picked.how
|
|
5789
6313
|
};
|
|
5790
6314
|
}
|
|
6315
|
+
if (form.direct) {
|
|
6316
|
+
return { bin: b.bin, args: baseArgs.concat([url]), isolated: false, watch: false, envKind: "sys", label: path2.basename(b.bin), pick: picked.how };
|
|
6317
|
+
}
|
|
5791
6318
|
const c = openCommand(pl, url);
|
|
5792
|
-
return { bin:
|
|
6319
|
+
if (!c) return { bin: null, args: [url], isolated: false, watch: false, envKind: "sys", label: null, pick: picked.how };
|
|
6320
|
+
return { bin: c.cmd, args: c.args, isolated: false, watch: false, envKind: "sys", label: c.cmd, pick: picked.how };
|
|
5793
6321
|
}
|
|
5794
6322
|
function binAvailable(bin) {
|
|
5795
6323
|
if (!bin) return false;
|
|
@@ -5806,21 +6334,21 @@ var require_browser = __commonJS({
|
|
|
5806
6334
|
const spawnWith = typeof opts.spawn === "function" ? opts.spawn : _spawnDetached;
|
|
5807
6335
|
const fail = (reason, extra) => Object.assign(outcome(Object.assign({ ok: false, reason, url }, extra)), { bin: null, isolated: false });
|
|
5808
6336
|
try {
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
else if (typeof opts.resolveDefault === "function") db = opts.resolveDefault(process.platform, opts.resolveDeps || {});
|
|
5812
|
-
else db = resolveDefaultBrowser(process.platform, opts.resolveDeps || {});
|
|
6337
|
+
const resolveInv = typeof opts.resolveInventory === "function" ? opts.resolveInventory : ((platform, deps) => detector.inventory(platform, deps));
|
|
6338
|
+
const inv = "inventory" in opts ? opts.inventory : resolveInv(process.platform, opts.resolveDeps || {});
|
|
5813
6339
|
const plan = isolatedPlan(process.platform, url, {
|
|
5814
|
-
|
|
6340
|
+
inventory: inv,
|
|
6341
|
+
pick: opts.pick,
|
|
5815
6342
|
profileDir: opts.profileDir,
|
|
5816
6343
|
size: opts.size,
|
|
5817
6344
|
lang: opts.lang
|
|
5818
6345
|
});
|
|
5819
|
-
|
|
6346
|
+
const evidence = { bin: plan.bin, engine: plan.label, via: plan.isolated ? "browser" : "dispatcher", diagnostics: launchDiagnostics(inv, plan, plan.pick) };
|
|
6347
|
+
if (!avail(plan.bin)) return fail("no-launcher", { evidence });
|
|
5820
6348
|
const env = plan.envKind === "anti" ? antiEnv : sysEnv;
|
|
5821
6349
|
const p = spawnWith(plan.bin, plan.args, env, plan.watch ? onExit : void 0);
|
|
5822
|
-
if (!p) return fail("spawn-failed");
|
|
5823
|
-
return Object.assign(outcome({ ok: true, confirmed: false, handedOff: true, url }), { bin: plan.label, isolated: plan.isolated });
|
|
6350
|
+
if (!p) return fail("spawn-failed", { evidence });
|
|
6351
|
+
return Object.assign(outcome({ ok: true, confirmed: false, handedOff: true, url, evidence }), { bin: plan.label, isolated: plan.isolated });
|
|
5824
6352
|
} catch (e) {
|
|
5825
6353
|
return fail("spawn-failed", { error: FAILURE_TEXT["spawn-failed"] + "\uFF08" + (e && e.code || e) + "\uFF09" });
|
|
5826
6354
|
}
|
|
@@ -5830,20 +6358,19 @@ var require_browser = __commonJS({
|
|
|
5830
6358
|
launchIsolated,
|
|
5831
6359
|
openCommand,
|
|
5832
6360
|
openPlan,
|
|
5833
|
-
ownsItsWindow,
|
|
5834
6361
|
isolatedPlan,
|
|
6362
|
+
pickLauncher,
|
|
6363
|
+
ownsItsWindow,
|
|
5835
6364
|
observeSpawn,
|
|
5836
6365
|
isSafeHttpUrl,
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
6366
|
+
binAvailable,
|
|
6367
|
+
listBrowsers,
|
|
6368
|
+
invalidateBrowsers,
|
|
6369
|
+
launchDiagnostics,
|
|
6370
|
+
// 探测层的解析原语经此转出(唯一实现处在 ./browser-inventory.js):门禁与消费方按同一出口取用,
|
|
6371
|
+
// 不在别处再写第二份平台解析。
|
|
5841
6372
|
engineOf,
|
|
5842
|
-
|
|
5843
|
-
tokenizeExec,
|
|
5844
|
-
regValueOf,
|
|
5845
|
-
exeFromCmdLine,
|
|
5846
|
-
binAvailable
|
|
6373
|
+
detector
|
|
5847
6374
|
};
|
|
5848
6375
|
}
|
|
5849
6376
|
});
|
|
@@ -17689,44 +18216,13 @@ var require_browser2 = __commonJS({
|
|
|
17689
18216
|
"src/domains/router/ops/browser.js"(exports2, module2) {
|
|
17690
18217
|
"use strict";
|
|
17691
18218
|
var platform = require_os();
|
|
18219
|
+
var desktop = require_desktop();
|
|
17692
18220
|
var fs2 = require("node:fs");
|
|
17693
18221
|
var os2 = require("node:os");
|
|
17694
18222
|
var path2 = require("node:path");
|
|
17695
18223
|
var crypto = require("node:crypto");
|
|
17696
18224
|
function graphicalEnv() {
|
|
17697
|
-
|
|
17698
|
-
try {
|
|
17699
|
-
const uid = process.getuid ? String(process.getuid()) : "";
|
|
17700
|
-
const xdgRun = process.env.XDG_RUNTIME_DIR || "/run/user/" + uid;
|
|
17701
|
-
if (!process.env.DISPLAY && !process.env.WAYLAND_DISPLAY) {
|
|
17702
|
-
const x11 = "/tmp/.X11-unix";
|
|
17703
|
-
try {
|
|
17704
|
-
if (fs2.existsSync(x11)) {
|
|
17705
|
-
const socks = fs2.readdirSync(x11).filter((f) => /^X\d+$/.test(f)).map((f) => parseInt(f.slice(1), 10)).sort((a, b) => a - b);
|
|
17706
|
-
if (socks.length > 0) {
|
|
17707
|
-
out.DISPLAY = ":" + socks[0];
|
|
17708
|
-
const xauth = path2.join(os2.homedir(), ".Xauthority");
|
|
17709
|
-
if (fs2.existsSync(xauth)) out.XAUTHORITY = xauth;
|
|
17710
|
-
}
|
|
17711
|
-
}
|
|
17712
|
-
} catch {
|
|
17713
|
-
}
|
|
17714
|
-
if (!out.DISPLAY) {
|
|
17715
|
-
try {
|
|
17716
|
-
if (fs2.existsSync(xdgRun)) {
|
|
17717
|
-
const wl = fs2.readdirSync(xdgRun).filter((f) => f.startsWith("wayland-")).sort();
|
|
17718
|
-
if (wl.length > 0) out.WAYLAND_DISPLAY = wl[0];
|
|
17719
|
-
}
|
|
17720
|
-
} catch {
|
|
17721
|
-
}
|
|
17722
|
-
}
|
|
17723
|
-
}
|
|
17724
|
-
if (!process.env.DBUS_SESSION_BUS_ADDRESS && fs2.existsSync(path2.join(xdgRun, "bus"))) {
|
|
17725
|
-
out.DBUS_SESSION_BUS_ADDRESS = "unix:path=" + path2.join(xdgRun, "bus");
|
|
17726
|
-
}
|
|
17727
|
-
} catch {
|
|
17728
|
-
}
|
|
17729
|
-
return out;
|
|
18225
|
+
return desktop.sessionEnv();
|
|
17730
18226
|
}
|
|
17731
18227
|
function openInBrowser(url, onExit) {
|
|
17732
18228
|
try {
|
|
@@ -17965,6 +18461,7 @@ var require_oauth = __commonJS({
|
|
|
17965
18461
|
confirmed: false,
|
|
17966
18462
|
handedOff: false,
|
|
17967
18463
|
reason: evidence.reason || "no-launcher",
|
|
18464
|
+
evidence: evidence.evidence || null,
|
|
17968
18465
|
error: (evidence.error || "\u65E0\u6CD5\u8C03\u8D77\u7CFB\u7EDF\u6D4F\u89C8\u5668") + "\uFF0C\u8BF7\u624B\u52A8\u6253\u5F00\u4E0B\u65B9\u5730\u5740\u5B8C\u6210\u6388\u6743"
|
|
17969
18466
|
};
|
|
17970
18467
|
}
|
|
@@ -25512,7 +26009,7 @@ var require_guard = __commonJS({
|
|
|
25512
26009
|
var fs2 = require("node:fs");
|
|
25513
26010
|
var path2 = require("node:path");
|
|
25514
26011
|
function owns(pathname) {
|
|
25515
|
-
return pathname === "/changelog" || pathname.startsWith("/guard/") || pathname === "/autostart" || pathname.startsWith("/settings/") || pathname.startsWith("/self-update/") || pathname === "/env/dsh" || pathname === "/env/status" || pathname === "/env/node-lts" || pathname === "/env/open-url" || pathname === "/ports" || pathname === "/shutdown";
|
|
26012
|
+
return pathname === "/changelog" || pathname.startsWith("/guard/") || pathname === "/autostart" || pathname.startsWith("/settings/") || pathname.startsWith("/self-update/") || pathname === "/env/dsh" || pathname === "/env/status" || pathname === "/env/node-lts" || pathname === "/env/open-url" || pathname === "/env/browsers" || pathname === "/ports" || pathname === "/shutdown";
|
|
25516
26013
|
}
|
|
25517
26014
|
function fetchDshChangelog(res, sup) {
|
|
25518
26015
|
const v = sup && sup.nativeManager ? sup.nativeManager.versionInfo() : {};
|
|
@@ -25688,6 +26185,14 @@ var require_guard = __commonJS({
|
|
|
25688
26185
|
if (req.method === "GET" && pathname === "/env/node-lts") {
|
|
25689
26186
|
return sup.nodeLtsStatus().then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: e.message }));
|
|
25690
26187
|
}
|
|
26188
|
+
if (req.method === "GET" && pathname === "/env/browsers") {
|
|
26189
|
+
if (!originAllowed(req, sup.config.apiPort)) {
|
|
26190
|
+
req.resume();
|
|
26191
|
+
return send(403, { ok: false, error: "cross-origin request rejected" });
|
|
26192
|
+
}
|
|
26193
|
+
const force = /[?&]force=1/.test(req.url || "");
|
|
26194
|
+
return Promise.resolve(browser.listBrowsers({ force })).then((r) => send(200, r)).catch((e) => send(500, { ok: false, error: "\u6D4F\u89C8\u5668\u63A2\u6D4B\u5931\u8D25\uFF1A" + (e && e.message || e) }));
|
|
26195
|
+
}
|
|
25691
26196
|
if (req.method === "POST" && pathname === "/env/open-url") {
|
|
25692
26197
|
if (!identity.loopback) {
|
|
25693
26198
|
req.resume();
|