Skip to content

feat: support MSIX/UWP browsers on Windows (Arc, DuckDuckGo)#563

Merged
moonD4rk merged 2 commits intomainfrom
feat/support-msix-browsers
Apr 10, 2026
Merged

feat: support MSIX/UWP browsers on Windows (Arc, DuckDuckGo)#563
moonD4rk merged 2 commits intomainfrom
feat/support-msix-browsers

Conversation

@moonD4rk
Copy link
Copy Markdown
Owner

Summary

Closes #548

Some Windows browsers are distributed as MSIX/UWP packages (Microsoft Store apps) whose data paths contain a dynamic publisher hash suffix (e.g., TheBrowserCompany.Arc_ttt1ap7aakyb4). This PR adds support for these browsers by allowing glob patterns in UserDataDir.

  • Add resolveGlobs to expand glob patterns in browser configs before discovery
  • Add Arc and DuckDuckGo browser configs for Windows with wildcard package paths
  • Consolidate TestPickFromConfigs_* into grouped table-driven TestPickFromConfigs
  • Add Glob integration test group (single match, multiple matches, no match, mixed, name filter)

How it works

Browser configs use glob patterns in UserDataDir:

UserDataDir: homeDir + "/AppData/Local/Packages/TheBrowserCompany.Arc_*/LocalCache/Local/Arc/User Data"

Before browser discovery, resolveGlobs expands all configs via filepath.Glob. Literal paths pass through unchanged; glob patterns expand to one config per match. The main pickFromConfigs loop remains flat and unmodified.

Verified on Windows 10

Browser          Profile   password   cookie   bookmark   history
Arc              Default   0          17       0          17
DuckDuckGo       Default   0          3        0          6

Test plan

  • go test -run TestPickFromConfigs/Glob ./browser/ — all 5 glob cases pass
  • go test -run TestResolveGlobs ./browser/ — all 7 unit cases pass
  • go test ./... — full suite passes
  • golangci-lint run — 0 issues
  • Windows 10 real machine: Arc and DuckDuckGo detected and extracted successfully

Add glob pattern support in UserDataDir to handle MSIX/UWP browsers
whose package directories contain a dynamic publisher hash suffix
(e.g., "TheBrowserCompany.Arc_ttt1ap7aakyb4").

- Add resolveGlobs to expand glob patterns before browser discovery
- Add Arc and DuckDuckGo browser configs for Windows
- Consolidate pickFromConfigs tests into grouped table-driven structure
- Add Glob integration test group covering single/multiple/no match cases
Copilot AI review requested due to automatic review settings April 10, 2026 16:00
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.45%. Comparing base (b3bbc0d) to head (fc4cd10).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #563      +/-   ##
==========================================
+ Coverage   73.28%   73.45%   +0.17%     
==========================================
  Files          48       48              
  Lines        1950     1963      +13     
==========================================
+ Hits         1429     1442      +13     
  Misses        384      384              
  Partials      137      137              
Flag Coverage Δ
unittests 73.45% <100.00%> (+0.17%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Windows support for MSIX/UWP-distributed browsers (e.g., Arc, DuckDuckGo) by allowing glob patterns in configured UserDataDir paths so dynamic package-suffix directories can be discovered during browser detection.

Changes:

  • Expand BrowserConfig.UserDataDir via filepath.Glob before discovery to support wildcard MSIX/UWP package paths.
  • Add Windows browser configs for Arc and DuckDuckGo using wildcard Packages/<AppName>_* paths.
  • Refactor and extend browser discovery tests with table-driven coverage for glob scenarios.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
browser/browser.go Adds resolveGlobs and applies it during pickFromConfigs to expand wildcard UserDataDir entries.
browser/browser_windows.go Adds Arc and DuckDuckGo Windows configs using MSIX/UWP Packages/..._* wildcard directories.
browser/consts.go Adds display-name constant for DuckDuckGo.
browser/browser_test.go Consolidates pickFromConfigs tests and adds glob-focused test coverage, plus unit tests for resolveGlobs.
Comments suppressed due to low confidence (1)

browser/browser.go:67

  • resolveGlobs is applied before the ProfilePath override. If a browser config uses a glob (e.g. Arc on Windows) and the user targets that browser with ProfilePath set, the configs get expanded to multiple entries and then each entry is overridden to the same ProfilePath, causing duplicate browser discoveries/outputs. Consider skipping glob resolution when opts.ProfilePath != "" && name != "all", or applying the override before expanding globs (or only resolving globs after filtering to the selected browser).
	configs = resolveGlobs(configs)

	var browsers []Browser
	for _, cfg := range configs {
		if name != "all" && cfg.Key != name {
			continue
		}

		// Override profile directory when targeting a specific browser.
		if opts.ProfilePath != "" && name != "all" {
			if cfg.Kind == types.Firefox {
				cfg.UserDataDir = filepath.Dir(filepath.Clean(opts.ProfilePath))
			} else {
				cfg.UserDataDir = opts.ProfilePath
			}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +108 to +113
// When a glob matches multiple directories, the config is duplicated so
// each resolved path is treated as a separate browser data directory.
func resolveGlobs(configs []types.BrowserConfig) []types.BrowserConfig {
var out []types.BrowserConfig
for _, cfg := range configs {
matches, _ := filepath.Glob(cfg.UserDataDir)
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filepath.Glob can return an error for a malformed pattern (e.g. unmatched [), but the error is currently ignored. This can silently disable discovery for a config with an invalid UserDataDir pattern. Consider handling the error (e.g., log it and fall back to the original config, or change resolveGlobs to return an error that pickFromConfigs can surface).

Suggested change
// When a glob matches multiple directories, the config is duplicated so
// each resolved path is treated as a separate browser data directory.
func resolveGlobs(configs []types.BrowserConfig) []types.BrowserConfig {
var out []types.BrowserConfig
for _, cfg := range configs {
matches, _ := filepath.Glob(cfg.UserDataDir)
// If a glob pattern is malformed, the error is logged and the original
// config is preserved so discovery behavior remains unchanged while making
// the misconfiguration visible.
//
// When a glob matches multiple directories, the config is duplicated so
// each resolved path is treated as a separate browser data directory.
func resolveGlobs(configs []types.BrowserConfig) []types.BrowserConfig {
var out []types.BrowserConfig
for _, cfg := range configs {
matches, err := filepath.Glob(cfg.UserDataDir)
if err != nil {
log.Errorf("invalid browser UserDataDir glob for %q: %q: %v", cfg.Key, cfg.UserDataDir, err)
out = append(out, cfg)
continue
}

Copilot uses AI. Check for mistakes.
Comment on lines +272 to 278
name: "glob single match",
configs: []types.BrowserConfig{
{Key: "yandex", Name: "Yandex", Kind: types.ChromiumYandex, UserDataDir: yandexDir},
{Key: "single", UserDataDir: filepath.Join(base, "ExactBrow*", "UserData")},
},
wantNames: []string{"Yandex"},
wantProfiles: []string{"Default"},
wantDirs: []string{filepath.Join(base, "ExactBrowser", "UserData")},
},
{
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subtest name "literal path not exists preserved" is grammatically awkward; consider renaming to something clearer like "literal path does not exist (preserved)" to improve readability when failures are reported.

Copilot uses AI. Check for mistakes.
@moonD4rk moonD4rk merged commit 454834c into main Apr 10, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Windows] Support MSIX/UWP browsers (Arc, DuckDuckGo)

3 participants