github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/engine/buffered_identify_ui.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package engine
     5  
     6  import (
     7  	"path"
     8  	"runtime"
     9  	"sync"
    10  
    11  	"github.com/keybase/client/go/libkb"
    12  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    13  )
    14  
    15  type start struct {
    16  	s string
    17  	r keybase1.IdentifyReason
    18  	f bool
    19  }
    20  
    21  type proofCheck struct {
    22  	social bool
    23  	p      keybase1.RemoteProof
    24  	l      keybase1.LinkCheckResult
    25  }
    26  
    27  type launchNetworkChecks struct {
    28  	i *keybase1.Identity
    29  	u *keybase1.User
    30  }
    31  
    32  type bufferedIdentifyUI struct {
    33  	libkb.Contextified
    34  	sync.Mutex
    35  	raw                 libkb.IdentifyUI
    36  	confirmIfSuppressed keybase1.ConfirmResult
    37  	bufferedMode        bool
    38  	start               *start
    39  	proofChecks         []proofCheck
    40  	cryptocurrency      []keybase1.Cryptocurrency
    41  	stellar             *keybase1.StellarAccount
    42  	launchNetworkChecks *launchNetworkChecks
    43  	keys                []keybase1.IdentifyKey
    44  	lastTrack           **keybase1.TrackSummary
    45  	suppressed          bool
    46  	userCard            *keybase1.UserCard
    47  }
    48  
    49  var _ libkb.IdentifyUI = (*bufferedIdentifyUI)(nil)
    50  
    51  func newBufferedIdentifyUI(g *libkb.GlobalContext, u libkb.IdentifyUI, c keybase1.ConfirmResult) *bufferedIdentifyUI {
    52  	return &bufferedIdentifyUI{
    53  		Contextified:        libkb.NewContextified(g),
    54  		raw:                 u,
    55  		confirmIfSuppressed: c,
    56  		bufferedMode:        true,
    57  	}
    58  }
    59  
    60  func (b *bufferedIdentifyUI) Start(m libkb.MetaContext, s string, r keybase1.IdentifyReason, f bool) error {
    61  	b.Lock()
    62  	defer b.Unlock()
    63  	b.start = &start{s, r, f}
    64  	return b.flush(m, false)
    65  }
    66  
    67  func (b *bufferedIdentifyUI) flush(m libkb.MetaContext, trackingBroke bool) (err error) {
    68  
    69  	// Look up the calling function for debugging purposes
    70  	pc := make([]uintptr, 10) // at least 1 entry needed
    71  	runtime.Callers(2, pc)
    72  	f := runtime.FuncForPC(pc[0])
    73  	caller := path.Base(f.Name())
    74  
    75  	m.Debug("+ bufferedIdentifyUI#flush(%v) [caller=%s, buffered=%v, suppressed=%v]", trackingBroke, caller, b.bufferedMode, b.suppressed)
    76  
    77  	if !trackingBroke && b.bufferedMode {
    78  		m.Debug("- bufferedIdentifyUI#flush: short-circuit")
    79  		return nil
    80  	}
    81  
    82  	defer func() {
    83  		b.flushCleanup()
    84  		m.Debug("- bufferedIdentifyUI#flush -> %v", err)
    85  	}()
    86  
    87  	if b.start != nil {
    88  		err = b.raw.Start(m, b.start.s, b.start.r, b.start.f)
    89  		if err != nil {
    90  			return err
    91  		}
    92  	}
    93  
    94  	for _, k := range b.keys {
    95  		err = b.raw.DisplayKey(m, k)
    96  		if err != nil {
    97  			return err
    98  		}
    99  	}
   100  
   101  	if b.lastTrack != nil {
   102  		err = b.raw.ReportLastTrack(m, *b.lastTrack)
   103  		if err != nil {
   104  			return err
   105  		}
   106  	}
   107  
   108  	if b.launchNetworkChecks != nil {
   109  		err = b.raw.LaunchNetworkChecks(m, b.launchNetworkChecks.i, b.launchNetworkChecks.u)
   110  		if err != nil {
   111  			return err
   112  		}
   113  	}
   114  
   115  	if b.userCard != nil {
   116  		err = b.raw.DisplayUserCard(m, *b.userCard)
   117  		if err != nil {
   118  			return err
   119  		}
   120  	}
   121  
   122  	for _, w := range b.proofChecks {
   123  		var err error
   124  		if w.social {
   125  			err = b.raw.FinishSocialProofCheck(m, w.p, w.l)
   126  		} else {
   127  			err = b.raw.FinishWebProofCheck(m, w.p, w.l)
   128  		}
   129  		if err != nil {
   130  			return err
   131  		}
   132  	}
   133  
   134  	for _, c := range b.cryptocurrency {
   135  		err = b.raw.DisplayCryptocurrency(m, c)
   136  		if err != nil {
   137  			return err
   138  		}
   139  	}
   140  
   141  	if b.stellar != nil {
   142  		err = b.raw.DisplayStellarAccount(m, *b.stellar)
   143  		if err != nil {
   144  			return err
   145  		}
   146  	}
   147  
   148  	return nil
   149  }
   150  
   151  func (b *bufferedIdentifyUI) flushCleanup() {
   152  	b.start = nil
   153  	b.proofChecks = nil
   154  	b.cryptocurrency = nil
   155  	b.stellar = nil
   156  	b.bufferedMode = false
   157  	b.launchNetworkChecks = nil
   158  	b.keys = nil
   159  	b.lastTrack = nil
   160  	b.userCard = nil
   161  }
   162  
   163  func (b *bufferedIdentifyUI) FinishWebProofCheck(m libkb.MetaContext, p keybase1.RemoteProof, l keybase1.LinkCheckResult) error {
   164  	b.Lock()
   165  	defer b.Unlock()
   166  	b.proofChecks = append(b.proofChecks, proofCheck{false, p, l})
   167  	return b.flush(m, l.BreaksTracking)
   168  }
   169  
   170  func (b *bufferedIdentifyUI) FinishSocialProofCheck(m libkb.MetaContext, p keybase1.RemoteProof, l keybase1.LinkCheckResult) error {
   171  	b.Lock()
   172  	defer b.Unlock()
   173  	b.proofChecks = append(b.proofChecks, proofCheck{true, p, l})
   174  	return b.flush(m, l.BreaksTracking)
   175  }
   176  
   177  func (b *bufferedIdentifyUI) Confirm(m libkb.MetaContext, o *keybase1.IdentifyOutcome) (keybase1.ConfirmResult, error) {
   178  	b.Lock()
   179  	defer b.Unlock()
   180  	if b.bufferedMode {
   181  		m.Debug("| bufferedIdentifyUI#Confirm: suppressing output")
   182  		b.suppressed = true
   183  		return b.confirmIfSuppressed, nil
   184  	}
   185  	m.Debug("| bufferedIdentifyUI#Confirm: enabling output")
   186  	b.flush(m, true)
   187  	return b.raw.Confirm(m, o)
   188  }
   189  
   190  func (b *bufferedIdentifyUI) DisplayCryptocurrency(m libkb.MetaContext, c keybase1.Cryptocurrency) error {
   191  	b.Lock()
   192  	defer b.Unlock()
   193  	b.cryptocurrency = append(b.cryptocurrency, c)
   194  	return b.flush(m, false)
   195  }
   196  
   197  func (b *bufferedIdentifyUI) DisplayStellarAccount(m libkb.MetaContext, c keybase1.StellarAccount) error {
   198  	b.Lock()
   199  	defer b.Unlock()
   200  	b.stellar = &c
   201  	return b.flush(m, false)
   202  }
   203  
   204  func (b *bufferedIdentifyUI) DisplayKey(m libkb.MetaContext, k keybase1.IdentifyKey) error {
   205  	b.Lock()
   206  	defer b.Unlock()
   207  	b.keys = append(b.keys, k)
   208  	return b.flush(m, k.BreaksTracking)
   209  }
   210  
   211  func (b *bufferedIdentifyUI) ReportLastTrack(m libkb.MetaContext, s *keybase1.TrackSummary) error {
   212  	b.Lock()
   213  	defer b.Unlock()
   214  	b.lastTrack = &s
   215  	return b.flush(m, false)
   216  }
   217  
   218  func (b *bufferedIdentifyUI) LaunchNetworkChecks(m libkb.MetaContext, i *keybase1.Identity, u *keybase1.User) error {
   219  	b.Lock()
   220  	defer b.Unlock()
   221  	b.launchNetworkChecks = &launchNetworkChecks{i, u}
   222  	return b.flush(m, i.BreaksTracking)
   223  }
   224  
   225  func (b *bufferedIdentifyUI) DisplayTrackStatement(m libkb.MetaContext, s string) error {
   226  	return b.raw.DisplayTrackStatement(m, s)
   227  }
   228  
   229  func (b *bufferedIdentifyUI) DisplayUserCard(m libkb.MetaContext, c keybase1.UserCard) error {
   230  	b.Lock()
   231  	defer b.Unlock()
   232  	b.userCard = &c
   233  	return b.flush(m, false)
   234  }
   235  
   236  func (b *bufferedIdentifyUI) ReportTrackToken(m libkb.MetaContext, t keybase1.TrackToken) error {
   237  	b.Lock()
   238  	defer b.Unlock()
   239  	if b.suppressed {
   240  		return nil
   241  	}
   242  	return b.raw.ReportTrackToken(m, t)
   243  }
   244  
   245  func (b *bufferedIdentifyUI) Cancel(m libkb.MetaContext) error {
   246  	b.Lock()
   247  	defer b.Unlock()
   248  
   249  	// Cancel should always go through to UI server
   250  	return b.raw.Cancel(m)
   251  }
   252  
   253  func (b *bufferedIdentifyUI) Finish(m libkb.MetaContext) error {
   254  	b.Lock()
   255  	defer b.Unlock()
   256  	if b.suppressed {
   257  		m.Debug("| bufferedIdentifyUI#Finish: suppressed")
   258  		return nil
   259  	}
   260  	m.Debug("| bufferedIdentifyUI#Finish: went through to UI")
   261  
   262  	// This is likely a noop since we already covered this case in the `Confirm` step
   263  	// above. However, if due a bug we forgot to call `Confirm` from the UI, this
   264  	// is still useful.
   265  	b.flush(m, true)
   266  
   267  	return b.raw.Finish(m)
   268  }
   269  
   270  func (b *bufferedIdentifyUI) DisplayTLFCreateWithInvite(m libkb.MetaContext, d keybase1.DisplayTLFCreateWithInviteArg) error {
   271  	return b.raw.DisplayTLFCreateWithInvite(m, d)
   272  }
   273  
   274  func (b *bufferedIdentifyUI) Dismiss(m libkb.MetaContext, s string, r keybase1.DismissReason) error {
   275  	return b.raw.Dismiss(m, s, r)
   276  }