1// Copyright 2017 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4// PerUserKeyUpkeepBackground runs PerUserKeyUpkeep in the background once in a while.
5// It rolls the per-user-key if the last one was involved in a deprovision.
6// See PerUserKeyUpkeep for more info.
7
8package engine
9
10import (
11	"sync"
12	"time"
13
14	"github.com/keybase/client/go/libkb"
15)
16
17var PerUserKeyUpkeepBackgroundSettings = BackgroundTaskSettings{
18	Start:        20 * time.Second, // Wait after starting the app
19	StartStagger: 20 * time.Second, // Wait an additional random amount.
20	WakeUp:       15 * time.Second, // Additional delay after waking from sleep.
21	Interval:     6 * time.Hour,    // Wait between checks
22	Limit:        5 * time.Minute,  // Time limit on each round
23}
24
25// PerUserKeyUpkeepBackground is an engine.
26type PerUserKeyUpkeepBackground struct {
27	libkb.Contextified
28	sync.Mutex
29
30	args *PerUserKeyUpkeepBackgroundArgs
31	task *BackgroundTask
32}
33
34type PerUserKeyUpkeepBackgroundArgs struct {
35	// Channels used for testing. Normally nil.
36	testingMetaCh     chan<- string
37	testingRoundResCh chan<- error
38}
39
40// NewPerUserKeyUpkeepBackground creates a PerUserKeyUpkeepBackground engine.
41func NewPerUserKeyUpkeepBackground(g *libkb.GlobalContext, args *PerUserKeyUpkeepBackgroundArgs) *PerUserKeyUpkeepBackground {
42	task := NewBackgroundTask(g, &BackgroundTaskArgs{
43		Name:     "PerUserKeyUpkeepBackground",
44		F:        PerUserKeyUpkeepBackgroundRound,
45		Settings: PerUserKeyUpkeepBackgroundSettings,
46
47		testingMetaCh:     args.testingMetaCh,
48		testingRoundResCh: args.testingRoundResCh,
49	})
50	return &PerUserKeyUpkeepBackground{
51		Contextified: libkb.NewContextified(g),
52		args:         args,
53		// Install the task early so that Shutdown can be called before RunEngine.
54		task: task,
55	}
56}
57
58// Name is the unique engine name.
59func (e *PerUserKeyUpkeepBackground) Name() string {
60	return "PerUserKeyUpkeepBackground"
61}
62
63// GetPrereqs returns the engine prereqs.
64func (e *PerUserKeyUpkeepBackground) Prereqs() Prereqs {
65	return Prereqs{}
66}
67
68// RequiredUIs returns the required UIs.
69func (e *PerUserKeyUpkeepBackground) RequiredUIs() []libkb.UIKind {
70	return []libkb.UIKind{}
71}
72
73// SubConsumers returns the other UI consumers for this engine.
74func (e *PerUserKeyUpkeepBackground) SubConsumers() []libkb.UIConsumer {
75	return []libkb.UIConsumer{&PerUserKeyUpkeep{}}
76}
77
78// Run starts the engine.
79// Returns immediately, kicks off a background goroutine.
80func (e *PerUserKeyUpkeepBackground) Run(m libkb.MetaContext) (err error) {
81	return RunEngine2(m, e.task)
82}
83
84func (e *PerUserKeyUpkeepBackground) Shutdown() {
85	e.task.Shutdown()
86}
87
88func PerUserKeyUpkeepBackgroundRound(m libkb.MetaContext) error {
89	if m.G().ConnectivityMonitor.IsConnected(m.Ctx()) == libkb.ConnectivityMonitorNo {
90		m.Debug("PerUserKeyUpkeepBackgroundRound giving up offline")
91		return nil
92	}
93
94	if !m.G().ActiveDevice.Valid() {
95		m.Debug("PerUserKeyUpkeepBackgroundRound not logged in")
96		return nil
97	}
98
99	if !m.G().LocalSigchainGuard().IsAvailable(m.Ctx(), "PerUserKeyUpkeepBackgroundRound") {
100		m.Debug("PerUserKeyUpkeepBackgroundRound yielding to guard")
101		return nil
102	}
103
104	arg := &PerUserKeyUpkeepArgs{}
105	eng := NewPerUserKeyUpkeep(m.G(), arg)
106	err := RunEngine2(m, eng)
107	return err
108}
109