@yufengtadian/freedom-cli 1.12.17 → 1.13.0

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.
Files changed (81) hide show
  1. package/lib/build.js +74 -9
  2. package/lib/cli.js +61 -3
  3. package/lib/init.js +9 -1
  4. package/lib/security.js +2 -2
  5. package/lib/utils.js +5 -2
  6. package/lib/verify.js +236 -0
  7. package/package.json +43 -39
  8. package/shell/darwin-arm64/freedom-shell +0 -0
  9. package/shell/linux-x64/freedom-shell +0 -0
  10. package/shell/win-x64/freedom-shell.exe +0 -0
  11. package/templates/go/go.mod +1 -7
  12. package/templates/go/go.sum +2 -2
  13. package/templates/go/main.go +22 -8
  14. package/templates/go/pkg/freedom/anti_debug_other.go +2 -3
  15. package/templates/go/pkg/freedom/anti_debug_windows.go +10 -12
  16. package/templates/go/pkg/freedom/assets/{index.html → default.html} +1 -1
  17. package/templates/go/pkg/freedom/assets/freedom.js +219 -21
  18. package/templates/go/pkg/freedom/assets_embed.go +11 -13
  19. package/templates/go/pkg/freedom/authenticode_other.go +11 -0
  20. package/templates/go/pkg/freedom/authenticode_windows.go +87 -0
  21. package/templates/go/pkg/freedom/backend_proc.go +295 -51
  22. package/templates/go/pkg/freedom/bridge.go +13 -2
  23. package/templates/go/pkg/freedom/capability.go +77 -0
  24. package/templates/go/pkg/freedom/center_other.go +3 -0
  25. package/templates/go/pkg/freedom/center_windows.go +64 -36
  26. package/templates/go/pkg/freedom/dispatch.go +60 -0
  27. package/templates/go/pkg/freedom/events_windows.go +319 -0
  28. package/templates/go/pkg/freedom/freedom.go +242 -92
  29. package/templates/go/pkg/freedom/msgwindow_windows.go +257 -0
  30. package/templates/go/pkg/freedom/osver_other.go +15 -0
  31. package/templates/go/pkg/freedom/osver_windows.go +121 -0
  32. package/templates/go/pkg/freedom/proc_hide_windows.go +2 -2
  33. package/templates/go/pkg/freedom/{configfile.go → resources.go} +56 -32
  34. package/templates/go/pkg/freedom/security.go +19 -12
  35. package/templates/go/pkg/freedom/singleinstance_other.go +10 -0
  36. package/templates/go/pkg/freedom/singleinstance_windows.go +145 -0
  37. package/templates/go/pkg/freedom/spawn_other.go +11 -0
  38. package/templates/go/pkg/freedom/spawn_windows.go +23 -0
  39. package/templates/go/pkg/freedom/store.go +458 -0
  40. package/templates/go/pkg/freedom/syscap_linux.go +278 -0
  41. package/templates/go/pkg/freedom/syscap_other.go +22 -0
  42. package/templates/go/pkg/freedom/syscap_windows.go +845 -0
  43. package/templates/go/pkg/freedom/sysint_common.go +70 -0
  44. package/templates/go/pkg/freedom/sysint_windows.go +426 -0
  45. package/templates/go/pkg/freedom/tray_common.go +12 -0
  46. package/templates/go/pkg/freedom/tray_linux.go +302 -0
  47. package/templates/go/pkg/freedom/tray_other.go +10 -0
  48. package/templates/go/pkg/freedom/tray_windows.go +536 -0
  49. package/templates/go/pkg/freedom/updater.go +372 -0
  50. package/templates/go/pkg/freedom/window_mgr.go +385 -0
  51. package/templates/go/pkg/freedom/window_other.go +32 -66
  52. package/templates/go/pkg/freedom/window_windows.go +406 -251
  53. package/templates/project-minimal/freedom.config.js +58 -0
  54. package/templates/project-minimal/index.html +41 -0
  55. package/templates/project-minimal/package.json +14 -0
  56. package/templates/project-minimal/src/main.js +19 -0
  57. package/templates/project-minimal/vite.config.js +18 -0
  58. package/templates/go/gen_config.go +0 -22
  59. package/templates/go/pkg/freedom/security_test.go +0 -153
  60. package/templates/go/webview_go/.github/workflows/ci.yaml +0 -62
  61. package/templates/go/webview_go/CHANGELOG.md +0 -15
  62. package/templates/go/webview_go/LICENSE +0 -22
  63. package/templates/go/webview_go/README.md +0 -50
  64. package/templates/go/webview_go/examples/basic/main.go +0 -12
  65. package/templates/go/webview_go/examples/bind/main.go +0 -38
  66. package/templates/go/webview_go/glue.c +0 -36
  67. package/templates/go/webview_go/go.mod +0 -3
  68. package/templates/go/webview_go/go.sum +0 -0
  69. package/templates/go/webview_go/libs/mswebview2/LICENSE +0 -27
  70. package/templates/go/webview_go/libs/mswebview2/include/WebView2.h +0 -23568
  71. package/templates/go/webview_go/libs/mswebview2/include/vendor.go +0 -2
  72. package/templates/go/webview_go/libs/mswebview2/vendor.go +0 -2
  73. package/templates/go/webview_go/libs/mswebview2/version.txt +0 -1
  74. package/templates/go/webview_go/libs/webview/LICENSE +0 -22
  75. package/templates/go/webview_go/libs/webview/include/vendor.go +0 -2
  76. package/templates/go/webview_go/libs/webview/include/webview.h +0 -3871
  77. package/templates/go/webview_go/libs/webview/vendor.go +0 -2
  78. package/templates/go/webview_go/libs/webview/version.txt +0 -1
  79. package/templates/go/webview_go/webview.cc +0 -1
  80. package/templates/go/webview_go/webview.go +0 -481
  81. package/templates/go/webview_go/webview_test.go +0 -50
@@ -0,0 +1,302 @@
1
+ //go:build linux
2
+
3
+ package freedom
4
+
5
+ /*
6
+ #cgo pkg-config: gtk+-3.0
7
+ #cgo CFLAGS: -Wno-deprecated-declarations
8
+ #include <gtk/gtk.h>
9
+
10
+ extern void goTrayClick(void);
11
+ extern void goTrayMenuItemActivate(int idx);
12
+
13
+ // GtkStatusIcon 自 GTK3.14 起标记 deprecated,但 legacy tray 协议在 KDE/XFCE/
14
+ // WSLg 仍广泛可用;AppIndicator(GDBus) 适配在未来自成一档。
15
+ static int ensureGtk(void) { return gtk_init_check(NULL, NULL) ? 1 : 0; }
16
+
17
+ static void onTrayActivate(GtkStatusIcon *icon, gpointer data) {
18
+ (void)icon; (void)data;
19
+ goTrayClick();
20
+ }
21
+
22
+ // 右键:弹出前端注册的菜单(popup-menu 信号),返回 TRUE 抑制默认行为。
23
+ static gboolean onTrayPopupMenu(GtkStatusIcon *icon, guint button, guint activate_time, gpointer data) {
24
+ (void)button; (void)activate_time; (void)data;
25
+ GtkWidget *menu = (GtkWidget*) g_object_get_data(G_OBJECT(icon), "freedom-menu");
26
+ if (menu != NULL) gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL);
27
+ return TRUE;
28
+ }
29
+
30
+ static void onMenuItemClick(GtkMenuItem *item, gpointer data) {
31
+ (void)item;
32
+ goTrayMenuItemActivate(GPOINTER_TO_INT(data));
33
+ }
34
+
35
+ static GtkStatusIcon* trayNewFromPng(const guint8 *png, gsize len) {
36
+ GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
37
+ gboolean ok = gdk_pixbuf_loader_write(loader, png, len, NULL);
38
+ ok = ok && gdk_pixbuf_loader_close(loader, NULL);
39
+ GdkPixbuf *pb = ok ? gdk_pixbuf_loader_get_pixbuf(loader) : NULL;
40
+ GtkStatusIcon *icon = pb ? gtk_status_icon_new_from_pixbuf(pb) : NULL;
41
+ g_object_unref(loader);
42
+ if (icon == NULL) return NULL;
43
+ g_signal_connect(icon, "activate", G_CALLBACK(onTrayActivate), NULL);
44
+ g_signal_connect(icon, "popup-menu", G_CALLBACK(onTrayPopupMenu), NULL);
45
+ gtk_status_icon_set_visible(icon, TRUE);
46
+ return icon;
47
+ }
48
+
49
+ static GtkStatusIcon* trayNewNamed(const char *name) {
50
+ GtkStatusIcon *icon = gtk_status_icon_new_from_icon_name(name);
51
+ g_signal_connect(icon, "activate", G_CALLBACK(onTrayActivate), NULL);
52
+ g_signal_connect(icon, "popup-menu", G_CALLBACK(onTrayPopupMenu), NULL);
53
+ gtk_status_icon_set_visible(icon, TRUE);
54
+ return icon;
55
+ }
56
+
57
+ static void traySetTooltip(GtkStatusIcon *icon, const char *tip) {
58
+ gtk_status_icon_set_tooltip_text(icon, tip);
59
+ }
60
+
61
+ static void trayDestroy(GtkStatusIcon *icon) {
62
+ gtk_status_icon_set_visible(icon, FALSE);
63
+ g_object_unref(icon);
64
+ }
65
+
66
+ // 菜单所有权:attach 时 ref_sink + set_data_full,重复 attach 自动释放旧菜单。
67
+ static void trayAttachMenu(GtkStatusIcon *icon, GtkWidget *menu) {
68
+ g_object_ref_sink(menu);
69
+ g_object_set_data_full(G_OBJECT(icon), "freedom-menu", menu, (GDestroyNotify) g_object_unref);
70
+ gtk_widget_show_all(menu);
71
+ }
72
+
73
+ static GtkWidget* menuNew(void) { return gtk_menu_new(); }
74
+
75
+ static GtkWidget* menuSubmenu(GtkWidget *parent, const char *label) {
76
+ GtkWidget *item = gtk_menu_item_new_with_label(label);
77
+ GtkWidget *sub = gtk_menu_new();
78
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), sub);
79
+ gtk_menu_shell_append(GTK_MENU_SHELL(parent), item);
80
+ return sub;
81
+ }
82
+
83
+ static void menuAppendItem(GtkWidget *menu, const char *label, int idx, gboolean sensitive) {
84
+ GtkWidget *item = gtk_menu_item_new_with_label(label);
85
+ gtk_widget_set_sensitive(item, sensitive);
86
+ g_signal_connect(item, "activate", G_CALLBACK(onMenuItemClick), GINT_TO_POINTER(idx));
87
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
88
+ }
89
+
90
+ static void menuAppendCheck(GtkWidget *menu, const char *label, int idx, gboolean checked, gboolean sensitive) {
91
+ GtkWidget *item = gtk_check_menu_item_new_with_label(label);
92
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), checked);
93
+ gtk_widget_set_sensitive(item, sensitive);
94
+ g_signal_connect(item, "activate", G_CALLBACK(onMenuItemClick), GINT_TO_POINTER(idx));
95
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
96
+ }
97
+
98
+ static void menuAppendSeparator(GtkWidget *menu) {
99
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
100
+ }
101
+ */
102
+ import "C"
103
+
104
+ import (
105
+ "encoding/json"
106
+ "fmt"
107
+ "sync"
108
+ "unsafe"
109
+ )
110
+
111
+ // M4 Linux 托盘(GtkStatusIcon,cgo):与 Windows 侧 trayCall 同一前端契约
112
+ // (tray.create/destroy/tooltip/menu;事件 tray:click / tray:menu({id}))。
113
+ // 限制:GtkStatusIcon 无双击信号(tray:double-click 不触发);menu.set(主窗口
114
+ // 原生菜单栏)与 GDBus StatusNotifierItem 适配未实装,托盘图标走 legacy
115
+ // system tray 协议(KDE/xfce/wmctrl 系支持;GNOME 需 AppIndicator 扩展)。
116
+ // GTK 调用须发生在 main线程:__freedom_tray 桥回调经 WebKit 消息处理器在
117
+ // GTK main loop 线程执行,天然满足;单测须先 gtk_init_check 且有 DISPLAY。
118
+
119
+ type linuxTrayState struct {
120
+ mu sync.Mutex
121
+ icon *C.GtkStatusIcon
122
+ items map[int32]string // 菜单条目序号 → 前端 id
123
+ emit func(event string, data interface{})
124
+ }
125
+
126
+ var linuxTray = &linuxTrayState{items: map[int32]string{}}
127
+
128
+ //export goTrayClick
129
+ func goTrayClick() {
130
+ linuxTray.mu.Lock()
131
+ emit := linuxTray.emit
132
+ linuxTray.mu.Unlock()
133
+ if emit != nil {
134
+ emit("tray:click", map[string]interface{}{"button": "left"})
135
+ }
136
+ }
137
+
138
+ //export goTrayMenuItemActivate
139
+ func goTrayMenuItemActivate(idx C.int) {
140
+ linuxTray.mu.Lock()
141
+ id := linuxTray.items[int32(idx)]
142
+ emit := linuxTray.emit
143
+ linuxTray.mu.Unlock()
144
+ if emit != nil {
145
+ emit("tray:menu", map[string]interface{}{"id": id})
146
+ }
147
+ }
148
+
149
+ // trayCall 处理前端 __freedom_tray 请求(Linux 实现,方法面与 Windows 对齐)。
150
+ func (a *App) trayCall(method string, paramsJSON string) (result interface{}, err error) {
151
+ defer func() {
152
+ if r := recover(); r != nil {
153
+ result = nil
154
+ err = fmt.Errorf("freedom: tray method %q panicked: %v", method, r)
155
+ }
156
+ }()
157
+
158
+ var args map[string]json.RawMessage
159
+ if len(paramsJSON) > 0 && paramsJSON != "null" {
160
+ if err := json.Unmarshal([]byte(paramsJSON), &args); err != nil {
161
+ return nil, fmt.Errorf("freedom: tray method %q: invalid args: %w", method, err)
162
+ }
163
+ }
164
+ argStr := func(k string) string {
165
+ if v, ok := args[k]; ok {
166
+ var s string
167
+ if json.Unmarshal(v, &s) == nil {
168
+ return s
169
+ }
170
+ }
171
+ return ""
172
+ }
173
+
174
+ switch method {
175
+ case "tray.create":
176
+ return nil, linuxTrayCreate(a, argStr("icon"), argStr("tooltip"))
177
+ case "tray.destroy":
178
+ linuxTrayDestroy()
179
+ return nil, nil
180
+ case "tray.tooltip":
181
+ linuxTray.mu.Lock()
182
+ icon := linuxTray.icon
183
+ linuxTray.mu.Unlock()
184
+ if icon == nil {
185
+ return nil, fmt.Errorf("tray: 托盘未创建")
186
+ }
187
+ tip := C.CString(argStr("tooltip"))
188
+ C.traySetTooltip(icon, tip)
189
+ C.free(unsafe.Pointer(tip))
190
+ return nil, nil
191
+ case "tray.menu":
192
+ linuxTray.mu.Lock()
193
+ icon := linuxTray.icon
194
+ linuxTray.mu.Unlock()
195
+ if icon == nil {
196
+ return nil, fmt.Errorf("tray: 托盘未创建")
197
+ }
198
+ var items []menuItem
199
+ if v, ok := args["items"]; ok {
200
+ if err := json.Unmarshal(v, &items); err != nil {
201
+ return nil, fmt.Errorf("tray: 菜单格式错误: %w", err)
202
+ }
203
+ }
204
+ linuxTraySetMenu(icon, items)
205
+ return nil, nil
206
+ case "menu.set":
207
+ return nil, fmt.Errorf("freedom: menu.set 在 linux 暂不支持(GTK 菜单栏待补)")
208
+ default:
209
+ return nil, fmt.Errorf("freedom: unknown tray method %q", method)
210
+ }
211
+ }
212
+
213
+ func linuxTrayCreate(a *App, iconDataURL, tooltip string) error {
214
+ if C.ensureGtk() == 0 {
215
+ return fmt.Errorf("freedom: 无可用显示服务(DISPLAY/Wayland),无法创建托盘")
216
+ }
217
+ png := dataURLToBytes(iconDataURL)
218
+ var icon *C.GtkStatusIcon
219
+ if len(png) > 0 {
220
+ icon = C.trayNewFromPng((*C.guint8)(unsafe.Pointer(&png[0])), C.gsize(len(png)))
221
+ } else {
222
+ name := C.CString("application-x-executable")
223
+ icon = C.trayNewNamed(name)
224
+ C.free(unsafe.Pointer(name))
225
+ }
226
+ if icon == nil {
227
+ return fmt.Errorf("freedom: 托盘图标创建失败(PNG 无法解析或无托盘协议支持)")
228
+ }
229
+ if tooltip != "" {
230
+ tip := C.CString(tooltip)
231
+ C.traySetTooltip(icon, tip)
232
+ C.free(unsafe.Pointer(tip))
233
+ }
234
+ linuxTray.mu.Lock()
235
+ old := linuxTray.icon
236
+ linuxTray.icon = icon
237
+ linuxTray.emit = a.Emit
238
+ linuxTray.mu.Unlock()
239
+ if old != nil {
240
+ C.trayDestroy(old)
241
+ }
242
+ return nil
243
+ }
244
+
245
+ func linuxTrayDestroy() {
246
+ linuxTray.mu.Lock()
247
+ icon := linuxTray.icon
248
+ linuxTray.icon = nil
249
+ linuxTray.items = map[int32]string{}
250
+ linuxTray.mu.Unlock()
251
+ if icon != nil {
252
+ C.trayDestroy(icon)
253
+ }
254
+ }
255
+
256
+ // linuxTraySetMenu 重建右键菜单并接管 icon 上的旧菜单释放(set_data_full)。
257
+ func linuxTraySetMenu(icon *C.GtkStatusIcon, items []menuItem) {
258
+ linuxTray.mu.Lock()
259
+ linuxTray.items = map[int32]string{}
260
+ var next int32
261
+ assign := func(id string) int32 {
262
+ h := next
263
+ next++
264
+ linuxTray.items[h] = id
265
+ return h
266
+ }
267
+ var build func(menu *C.GtkWidget, list []menuItem)
268
+ build = func(menu *C.GtkWidget, list []menuItem) {
269
+ for _, it := range list {
270
+ label := C.CString(it.Label)
271
+ switch {
272
+ case it.Type == "separator":
273
+ C.menuAppendSeparator(menu)
274
+ case it.Type == "submenu" || len(it.Submenu) > 0:
275
+ sub := C.menuSubmenu(menu, label)
276
+ // 父条目无动作,仅展开;子条目递归编号。
277
+ assign(it.ID)
278
+ build(sub, it.Submenu)
279
+ default:
280
+ idx := assign(it.ID)
281
+ sensitive := C.gboolean(1)
282
+ if it.Enabled != nil && !*it.Enabled {
283
+ sensitive = 0
284
+ }
285
+ if it.Checked != nil {
286
+ checked := C.gboolean(0)
287
+ if *it.Checked {
288
+ checked = 1
289
+ }
290
+ C.menuAppendCheck(menu, label, C.int(idx), checked, sensitive)
291
+ } else {
292
+ C.menuAppendItem(menu, label, C.int(idx), sensitive)
293
+ }
294
+ }
295
+ C.free(unsafe.Pointer(label))
296
+ }
297
+ }
298
+ menu := C.menuNew()
299
+ build(menu, items)
300
+ C.trayAttachMenu(icon, menu)
301
+ linuxTray.mu.Unlock()
302
+ }
@@ -0,0 +1,10 @@
1
+ //go:build !windows && !linux
2
+
3
+ package freedom
4
+
5
+ import "fmt"
6
+
7
+ // trayCall 非 Windows/Linux 平台暂不提供系统托盘与原生菜单栏。Linux 实装见 tray_linux.go(M4)。
8
+ func (a *App) trayCall(method string, paramsJSON string) (interface{}, error) {
9
+ return nil, fmt.Errorf("freedom: tray method %q is not supported on this platform", method)
10
+ }