Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: chromium manifest #8

Merged
merged 2 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ snapcrafts:
apps:
armaria:
command: armaria
plugs: ["dot-mozilla", "dot-chrome"]
plugs: ["dot-mozilla", "dot-chrome", "dot-chromium"]
armaria-host:
command: armaria-host
plugs:
Expand All @@ -178,3 +178,7 @@ snapcrafts:
interface: personal-files
write:
- $HOME/.config/google-chrome/NativeMessagingHosts
dot-chromium:
interface: personal-files
write:
- $HOME/.config/chromium/NativeMessagingHosts
28 changes: 26 additions & 2 deletions cmd/cli/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ type ManifestCmd struct {

// InstallManifestCmd is a CLI command to the app manifest.
type InstallManifestCmd struct {
Firefox InstallFirefoxManifestCmd `cmd:"" help:"Install the app manifest for Firefox."`
Chrome InstallChromeManifestCmd `cmd:"" help:"Install the app manifest for Chrome."`
Firefox InstallFirefoxManifestCmd `cmd:"" help:"Install the app manifest for Firefox."`
Chrome InstallChromeManifestCmd `cmd:"" help:"Install the app manifest for Chrome."`
Chromium InstallChromiumManifestCmd `cmd:"" help:"Install the app manifest for Chromium."`
}

// AddBookCmd is a CLI command to add a bookmark.
Expand Down Expand Up @@ -735,3 +736,26 @@ func (r *InstallChromeManifestCmd) Run(ctx *Context) error {

return nil
}

// InstallChromiumManifestCmd is a CLI command to install the app manifest for Chromium.
type InstallChromiumManifestCmd struct {
}

// Run install app manifest for Chromium.
func (r *InstallChromiumManifestCmd) Run(ctx *Context) error {
start := time.Now()

err := armariaapi.InstallManifestChromium()

if err != nil {
formatError(ctx.Writer, ctx.Formatter, err)
ctx.ReturnCode(1)
return nil
}

elapsed := time.Since(start)

formatSuccess(ctx.Writer, ctx.Formatter, fmt.Sprintf("Installed in %s", elapsed))

return nil
}
35 changes: 35 additions & 0 deletions internal/paths/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,41 @@ func chromeManifestInternal(goos string, getenv getenvFn, userHome userHomeFn, j
return join(folder, manifestFilename), nil
}

// Chromium Manifest gets the path to the Chromium app manifest.
// The path is different per platform and maps to the following:
// - Linux: ~/.config/chromium/NativeMessagingHosts
// - Windows: ~/AppData/Local/Armaria
// - Mac: ~/Library/Application Support/Chromium
func ChromiumManifest() (string, error) {
return chromiumManifestInternal(runtime.GOOS, os.Getenv, os.UserHomeDir, filepath.Join, os.MkdirAll)
}

// chromiumManifestInternal allows DI for ChromiumManifest.
func chromiumManifestInternal(goos string, getenv getenvFn, userHome userHomeFn, join joinFn, mkDirAll mkDirAllFn) (string, error) {
home, err := realHome(getenv, userHome)
if err != nil {
return "", fmt.Errorf("error getting real home dir while getting chromium manifest path: %w", err)
}

var folder string
if goos == "linux" {
folder = join(home, ".config", "chromium", "NativeMessagingHosts")
} else if goos == "windows" {
// The manifest can be anywhere in Windows, but it needs a supporting registry entry.
folder = join(home, "AppData", "Local", "Armaria")
} else if goos == "darwin" {
folder = join(home, "Library", "Application Support", "Chromium", "NativeMessagingHosts")
} else {
panic("Unsupported operating system")
}

if err = mkDirAll(folder, os.ModePerm); err != nil {
return "", fmt.Errorf("error creating folder while getting chromium manifest path: %w", err)
}

return join(folder, manifestFilename), nil
}

// realHome returns the true home directory of the current user.
// Snap will replace the $HOME env var with a sandboxed directory.
func realHome(getenv getenvFn, userHome userHomeFn) (string, error) {
Expand Down
74 changes: 74 additions & 0 deletions internal/paths/paths_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,77 @@ func TestChromeManifestPath(t *testing.T) {
})
}
}

func TestChromiumManifestPath(t *testing.T) {
type test struct {
goos string
folderPath string
folderCreated bool
snapRealHome string
manifestPath string
}

tests := []test{
{
goos: "windows",
folderPath: "~/AppData/Local/Armaria",
folderCreated: true,
manifestPath: "~/AppData/Local/Armaria/armaria.json",
},
{
goos: "linux",
folderPath: "~/.config/chromium/NativeMessagingHosts",
folderCreated: true,
manifestPath: "~/.config/chromium/NativeMessagingHosts/armaria.json",
},
{
goos: "linux",
folderPath: "~/snap/.config/chromium/NativeMessagingHosts",
folderCreated: true,
snapRealHome: "~/snap",
manifestPath: "~/snap/.config/chromium/NativeMessagingHosts/armaria.json",
},
{
goos: "darwin",
folderPath: "~/Library/Application Support/Chromium/NativeMessagingHosts",
folderCreated: true,
manifestPath: "~/Library/Application Support/Chromium/NativeMessagingHosts/armaria.json",
},
}

userHome := func() (string, error) {
return "~", nil
}

for _, tc := range tests {
t.Run(fmt.Sprintf("GOOS: %s, SNAP_REAL_HOME: %s", tc.goos, tc.snapRealHome), func(t *testing.T) {
folderCreated := false

mkDirAll := func(path string, perm os.FileMode) error {
folderCreated = true
if path != tc.folderPath {
t.Errorf("folder: got %+v; want %+v", path, tc.folderPath)
}

return nil
}

getenv := func(key string) string {
return tc.snapRealHome
}

got, err := chromiumManifestInternal(tc.goos, getenv, userHome, path.Join, mkDirAll)
if err != nil {
t.Fatalf("unexpected error: %+v", err)
}

if folderCreated != tc.folderCreated {
t.Fatalf("folder created: got %+v; want %+v", folderCreated, tc.folderCreated)
}

if got != tc.manifestPath {
t.Errorf("manfiestPath: got %+v; want %+v", got, tc.manifestPath)
}
})
}
}
12 changes: 11 additions & 1 deletion pkg/api/install_manfiest.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ func InstallManifestChrome() error {
return installManifest(path)
}

// InstallManifestChromium installs the app manifest for Firefox.
func InstallManifestChromium() error {
path, err := paths.ChromiumManifest()
if err != nil {
return fmt.Errorf("error getting chromium manfiest path while installing manifest: %w", err)
}

return installManifest(path)
}

// installManifest installs the app manifest.
func installManifest(path string) error {
hostPath, err := paths.Host()
Expand All @@ -45,7 +55,7 @@ func installManifest(path string) error {
Path: hostPath,
HostType: "stdio",
AllowedExtensions: []string{"[email protected]"},
AllowedOrigins: []string{"chrome-extension://armaria/"},
AllowedOrigins: []string{"chrome-extension://cahkgigfdplmhgjbioakkgennhncioli/"},
}

buffer, err := json.Marshal(manifest)
Expand Down