1// Copyright 2017 Keybase, Inc. All rights reserved. Use of 2// this source code is governed by the included BSD license. 3 4// PerUserKeyUpgradeBackground runs PerUserKeyUpgrade in the background once in a while. 5// It brings users without per-user-keys up to having them. 6// Note that this engine is long-lived and potentially has to deal with being 7// logged out and logged in as a different user, etc. 8 9package engine 10 11import ( 12 "sync" 13 "time" 14 15 "github.com/keybase/client/go/libkb" 16) 17 18var PerUserKeyUpgradeBackgroundSettings = BackgroundTaskSettings{ 19 Start: 30 * time.Second, // Wait after starting the app 20 StartStagger: 10 * time.Second, // Wait an additional random amount. 21 WakeUp: 10 * time.Second, // Additional delay after waking from sleep. 22 Interval: 1 * time.Hour, // Wait between checks 23 Limit: 5 * time.Minute, // Time limit on each round 24} 25 26// PerUserKeyUpgradeBackground is an engine. 27type PerUserKeyUpgradeBackground struct { 28 libkb.Contextified 29 sync.Mutex 30 31 args *PerUserKeyUpgradeBackgroundArgs 32 task *BackgroundTask 33} 34 35type PerUserKeyUpgradeBackgroundArgs struct { 36 // Channels used for testing. Normally nil. 37 testingMetaCh chan<- string 38 testingRoundResCh chan<- error 39} 40 41// NewPerUserKeyUpgradeBackground creates a PerUserKeyUpgradeBackground engine. 42func NewPerUserKeyUpgradeBackground(g *libkb.GlobalContext, args *PerUserKeyUpgradeBackgroundArgs) *PerUserKeyUpgradeBackground { 43 task := NewBackgroundTask(g, &BackgroundTaskArgs{ 44 Name: "PerUserKeyUpgradeBackground", 45 F: PerUserKeyUpgradeBackgroundRound, 46 Settings: PerUserKeyUpgradeBackgroundSettings, 47 48 testingMetaCh: args.testingMetaCh, 49 testingRoundResCh: args.testingRoundResCh, 50 }) 51 return &PerUserKeyUpgradeBackground{ 52 Contextified: libkb.NewContextified(g), 53 args: args, 54 // Install the task early so that Shutdown can be called before RunEngine. 55 task: task, 56 } 57} 58 59// Name is the unique engine name. 60func (e *PerUserKeyUpgradeBackground) Name() string { 61 return "PerUserKeyUpgradeBackground" 62} 63 64// GetPrereqs returns the engine prereqs. 65func (e *PerUserKeyUpgradeBackground) Prereqs() Prereqs { 66 return Prereqs{} 67} 68 69// RequiredUIs returns the required UIs. 70func (e *PerUserKeyUpgradeBackground) RequiredUIs() []libkb.UIKind { 71 return []libkb.UIKind{} 72} 73 74// SubConsumers returns the other UI consumers for this engine. 75func (e *PerUserKeyUpgradeBackground) SubConsumers() []libkb.UIConsumer { 76 return []libkb.UIConsumer{&PerUserKeyUpgrade{}} 77} 78 79// Run starts the engine. 80// Returns immediately, kicks off a background goroutine. 81func (e *PerUserKeyUpgradeBackground) Run(m libkb.MetaContext) (err error) { 82 return RunEngine2(m, e.task) 83} 84 85func (e *PerUserKeyUpgradeBackground) Shutdown() { 86 e.task.Shutdown() 87} 88 89func PerUserKeyUpgradeBackgroundRound(m libkb.MetaContext) error { 90 if !m.G().Env.GetUpgradePerUserKey() { 91 m.Debug("PerUserKeyUpgradeBackground disabled") 92 return nil 93 } 94 95 if !m.G().LocalSigchainGuard().IsAvailable(m.Ctx(), "PerUserKeyUpgradeBackgroundRound") { 96 m.Debug("PerUserKeyUpgradeBackground yielding to guard") 97 return nil 98 } 99 100 if m.G().ConnectivityMonitor.IsConnected(m.Ctx()) == libkb.ConnectivityMonitorNo { 101 m.Debug("PerUserKeyUpgradeBackground giving up offline") 102 return nil 103 } 104 105 // Do a fast local check to see if our work is done. 106 pukring, err := m.G().GetPerUserKeyring(m.Ctx()) 107 if err != nil { 108 m.Debug("PerUserKeyUpgradeBackground error getting keyring: %v", err) 109 // ignore error 110 } 111 if err == nil { 112 if pukring.HasAnyKeys() { 113 m.Debug("PerUserKeyUpgradeBackground already has keys") 114 return nil 115 } 116 } 117 118 arg := &PerUserKeyUpgradeArgs{} 119 eng := NewPerUserKeyUpgrade(m.G(), arg) 120 err = RunEngine2(m, eng) 121 return err 122} 123