Skip to content

Commit ac8f733

Browse files
committed
feat: try support darwin
1 parent d1a361e commit ac8f733

File tree

9 files changed

+137
-61
lines changed

9 files changed

+137
-61
lines changed
File renamed without changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//go:build darwin
2+
3+
package openBrowser
4+
5+
import (
6+
"os"
7+
"os/exec"
8+
"uni-token-service/constants"
9+
)
10+
11+
func OpenBrowser(targetUser string, url string) error {
12+
var cmd *exec.Cmd
13+
if constants.ShouldChangeUser {
14+
// Use sudo to run as the target user on macOS
15+
cmd = exec.Command("sudo", "-u", targetUser, "open", url)
16+
} else {
17+
// Use the native macOS 'open' command
18+
cmd = exec.Command("open", url)
19+
}
20+
21+
cmd.Stdout = os.Stdout
22+
cmd.Stderr = os.Stderr
23+
return cmd.Run()
24+
}

service/logic/open_browser/stub.go

Lines changed: 0 additions & 9 deletions
This file was deleted.

service/logic/url_scheme/common.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package urlScheme
2+
3+
type UrlSchemeRegisterOption struct {
4+
Scheme string
5+
AppName string
6+
ExecutablePath string
7+
}

service/logic/url_scheme/darwin.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//go:build darwin
2+
3+
package urlScheme
4+
5+
import (
6+
"fmt"
7+
"os"
8+
"os/exec"
9+
"path/filepath"
10+
"strings"
11+
)
12+
13+
func RegisterURLScheme(options UrlSchemeRegisterOption) error {
14+
// On macOS, URL schemes are typically registered through:
15+
// 1. Creating an app bundle with Info.plist containing URL scheme registration
16+
// 2. Using Launch Services to register the scheme handler
17+
18+
// For command-line applications, we'll create a minimal app bundle
19+
// and register it with the system
20+
21+
homeDir, err := os.UserHomeDir()
22+
if err != nil {
23+
return fmt.Errorf("failed to get user home directory: %w", err)
24+
}
25+
26+
// Create app bundle structure in ~/Applications/
27+
appName := options.AppName + ".app"
28+
appBundlePath := filepath.Join(homeDir, "Applications", appName)
29+
contentsPath := filepath.Join(appBundlePath, "Contents")
30+
macOSPath := filepath.Join(contentsPath, "MacOS")
31+
32+
// Create directories
33+
if err := os.MkdirAll(macOSPath, 0755); err != nil {
34+
return fmt.Errorf("failed to create app bundle directories: %w", err)
35+
}
36+
37+
// Create Info.plist with URL scheme registration
38+
infoPlistPath := filepath.Join(contentsPath, "Info.plist")
39+
infoPlistContent := fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
40+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
41+
<plist version="1.0">
42+
<dict>
43+
<key>CFBundleExecutable</key>
44+
<string>%s</string>
45+
<key>CFBundleIdentifier</key>
46+
<string>com.%s.%s</string>
47+
<key>CFBundleName</key>
48+
<string>%s</string>
49+
<key>CFBundleVersion</key>
50+
<string>1.0</string>
51+
<key>CFBundleShortVersionString</key>
52+
<string>1.0</string>
53+
<key>CFBundlePackageType</key>
54+
<string>APPL</string>
55+
<key>CFBundleURLTypes</key>
56+
<array>
57+
<dict>
58+
<key>CFBundleURLName</key>
59+
<string>%s URL Handler</string>
60+
<key>CFBundleURLSchemes</key>
61+
<array>
62+
<string>%s</string>
63+
</array>
64+
</dict>
65+
</array>
66+
</dict>
67+
</plist>`,
68+
options.AppName,
69+
strings.ToLower(options.AppName),
70+
strings.ToLower(options.AppName),
71+
options.AppName,
72+
options.AppName,
73+
options.Scheme)
74+
75+
if err := os.WriteFile(infoPlistPath, []byte(infoPlistContent), 0644); err != nil {
76+
return fmt.Errorf("failed to write Info.plist: %w", err)
77+
}
78+
79+
// Create executable wrapper script in the app bundle
80+
executablePath := filepath.Join(macOSPath, options.AppName)
81+
wrapperScript := fmt.Sprintf(`#!/bin/bash
82+
# URL scheme handler wrapper for %s
83+
exec "%s" url "$@"
84+
`, options.AppName, options.ExecutablePath)
85+
86+
if err := os.WriteFile(executablePath, []byte(wrapperScript), 0755); err != nil {
87+
return fmt.Errorf("failed to write wrapper executable: %w", err)
88+
}
89+
90+
// Register the app bundle with Launch Services
91+
// This makes the system aware of the URL scheme handler
92+
cmd := exec.Command("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister",
93+
"-f", appBundlePath)
94+
95+
if output, err := cmd.CombinedOutput(); err != nil {
96+
return fmt.Errorf("failed to register app bundle with Launch Services: %w\nOutput: %s", err, output)
97+
}
98+
99+
// Optional: Set as default handler for the scheme
100+
// This requires the user to approve the change, so we'll skip it for now
101+
// cmd = exec.Command("open", "-a", appBundlePath, fmt.Sprintf("%s://test", options.Scheme))
102+
103+
return nil
104+
}

service/logic/url_scheme/linux.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,7 @@ import (
99
"path/filepath"
1010
)
1111

12-
// Stub for Windows function when building on Linux
13-
func registerURLSchemeWindows(options UrlSchemeRegisterOption) error {
14-
return fmt.Errorf("windows URL scheme registration not available on linux")
15-
}
16-
17-
// registerURLSchemeForLinux registers URL scheme on Linux
18-
func registerURLSchemeLinux(options UrlSchemeRegisterOption) error {
12+
func RegisterURLScheme(options UrlSchemeRegisterOption) error {
1913
homeDir, err := os.UserHomeDir()
2014
if err != nil {
2115
return fmt.Errorf("failed to get user home directory: %w", err)

service/logic/url_scheme/register.go

Lines changed: 0 additions & 25 deletions
This file was deleted.

service/logic/url_scheme/stub.go

Lines changed: 0 additions & 13 deletions
This file was deleted.

service/logic/url_scheme/windows.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,7 @@ import (
1010
"golang.org/x/sys/windows/registry"
1111
)
1212

13-
// Stub for Linux function when building on Windows
14-
func registerURLSchemeLinux(options UrlSchemeRegisterOption) error {
15-
return fmt.Errorf("Linux URL scheme registration not available on Windows")
16-
}
17-
18-
// registerURLSchemeForWindows registers URL scheme on Windows
19-
func registerURLSchemeWindows(options UrlSchemeRegisterOption) error {
13+
func RegisterURLScheme(options UrlSchemeRegisterOption) error {
2014
exePath := filepath.ToSlash(options.ExecutablePath)
2115

2216
// Build registry path

0 commit comments

Comments
 (0)