betterbird: lock the ask to be the default mail client off, so it never shows at a start (hq issue 345)
mesh/merge-gate head 481e44cdaa29 merged into trunk 23ea0f431faf — pass: builds betterbird, sent nowhere; no bus step; 1 wait(s) for a person; every machin…
mesh/repo-check head 481e44cdaa29 merged into trunk 23ea0f431faf — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered

Betterbird's own default asks at every start with a window to become the default for mail, news, feeds and
calendar files. The policy locks mail.shell.checkDefaultClient off, which wins over a profile's own value, and
betterbird_check says when a node would still ask.
This commit is contained in:
jochen
2026-10-12 20:17:38 +02:00
parent 23ea0f431f
commit 481e44cdaa
5 changed files with 117 additions and 4 deletions
@@ -30,6 +30,10 @@ const (
// owlFile is Owl's xpi as the mesh placed it, and the URL the policy installs it from.
owlFile = installDir + "/owl/owl.xpi"
owlID = "owl@beonex.com"
// defaultClientPref is Betterbird's ask at its start to be the default mail, news, feed and calendar
// client (Thunderbird's all-thunderbird.js: pref("mail.shell.checkDefaultClient", true); messenger.js opens
// systemIntegrationDialog.xhtml while it is true). The module's policy locks it off (novox/hq issue 345).
defaultClientPref = "mail.shell.checkDefaultClient"
// preparation is the tools' program as the module places it for its start (betterbird-tools prepare).
preparation = "/usr/local/lib/mesh-betterbird/betterbird-tools"
// versionsURL is where Betterbird publishes its newest build per major version: what its own updater
@@ -167,7 +171,8 @@ func (m *Machine) policyState() string {
if why := policyProblem(raw); why != "" {
return "placed, and " + why
}
return "placed: Betterbird's updater off, Owl installed into every profile from the mesh's xpi, its updates off"
return "placed: Betterbird's updater off, Owl installed into every profile from the mesh's xpi, its updates off, " +
"and the ask to be the default mail client locked off"
}
// policyProblem is what the policy fails to say of what ADR 0316 asks, or "".
@@ -180,6 +185,10 @@ func policyProblem(raw []byte) string {
URL string `json:"install_url"`
Disabled bool `json:"updates_disabled"`
} `json:"ExtensionSettings"`
Preferences map[string]struct {
Value any `json:"Value"`
Status string `json:"Status"`
} `json:"Preferences"`
} `json:"policies"`
}
if err := json.Unmarshal(raw, &p); err != nil {
@@ -196,9 +205,37 @@ func policyProblem(raw []byte) string {
case !owl.Disabled:
return "it leaves Owl's updates on"
}
if pr, ok := p.Policies.Preferences[defaultClientPref]; !ok || pr.Value != false || pr.Status != "locked" {
return "it does not lock Betterbird's ask to be the default mail client off (Preferences " + defaultClientPref + ": false, locked)"
}
return ""
}
// defaultClientAsk says why Betterbird asks at its start to be the default mail client, or "" when it does
// not: the module's policy locks the ask off, else the profile's user.js (which wins at the start) or prefs.js
// turns it off. Betterbird's own default is to ask.
func (m *Machine) defaultClientAsk(profile string) string {
raw, err := readBounded(m.path(policyFile))
if err == nil && !strings.Contains(policyProblem(raw), defaultClientPref) {
return ""
}
if profile != "" {
for _, f := range []string{"user.js", "prefs.js"} {
b, err := readBounded(filepath.Join(profile, f))
if err != nil {
continue
}
if v, ok := readPrefs(b)[defaultClientPref]; ok {
if v == "false" {
return ""
}
return "the profile's " + f + " sets " + defaultClientPref + " to " + v + " and no policy locks it off"
}
}
}
return "no policy locks " + defaultClientPref + " off and Betterbird's default is to ask"
}
// xpiVersion is the version an add-on's manifest.json says, or "" when it cannot be read.
func xpiVersion(path string) string {
r, err := zip.OpenReader(path)