@@ -20,7 +20,6 @@ import (
2020 "tailscale.com/ipn/ipnauth"
2121 "tailscale.com/ipn/ipnext"
2222 "tailscale.com/tailcfg"
23- "tailscale.com/tsd"
2423 "tailscale.com/types/logger"
2524 "tailscale.com/util/execqueue"
2625 "tailscale.com/util/testenv"
@@ -131,15 +130,32 @@ type Backend interface {
131130 // SwitchToBestProfile switches to the best profile for the current state of the system.
132131 // The reason indicates why the profile is being switched.
133132 SwitchToBestProfile (reason string )
133+
134+ SendNotify (ipn.Notify )
135+ ipnext.SafeBackend
134136}
135137
136138// NewExtensionHost returns a new [ExtensionHost] which manages registered extensions for the given backend.
137139// The extensions are instantiated, but are not initialized until [ExtensionHost.Init] is called.
138140// It returns an error if instantiating any extension fails.
141+ func NewExtensionHost (logf logger.Logf , b Backend ) (* ExtensionHost , error ) {
142+ return newExtensionHost (logf , b )
143+ }
144+
145+ func NewExtensionHostForTest (logf logger.Logf , b Backend , overrideExts ... * ipnext.Definition ) (* ExtensionHost , error ) {
146+ if ! testenv .InTest () {
147+ panic ("use outside of test" )
148+ }
149+ return newExtensionHost (logf , b , overrideExts ... )
150+ }
151+
152+ // newExtensionHost is the shared implementation of [NewExtensionHost] and
153+ // [NewExtensionHostForTest].
139154//
140- // If overrideExts is non-nil, the registered extensions are ignored and the provided extensions are used instead.
141- // Overriding extensions is primarily used for testing.
142- func NewExtensionHost (logf logger.Logf , sys * tsd.System , b Backend , overrideExts ... * ipnext.Definition ) (_ * ExtensionHost , err error ) {
155+ // If overrideExts is non-nil, the registered extensions are ignored and the
156+ // provided extensions are used instead. Overriding extensions is primarily used
157+ // for testing.
158+ func newExtensionHost (logf logger.Logf , b Backend , overrideExts ... * ipnext.Definition ) (_ * ExtensionHost , err error ) {
143159 host := & ExtensionHost {
144160 b : b ,
145161 logf : logger .WithPrefix (logf , "ipnext: " ),
@@ -172,7 +188,7 @@ func NewExtensionHost(logf logger.Logf, sys *tsd.System, b Backend, overrideExts
172188
173189 host .allExtensions = make ([]ipnext.Extension , 0 , numExts )
174190 for _ , d := range exts {
175- ext , err := d .MakeExtension (logf , sys )
191+ ext , err := d .MakeExtension (logf , b )
176192 if errors .Is (err , ipnext .SkipExtension ) {
177193 // The extension wants to be skipped.
178194 host .logf ("%q: %v" , d .Name (), err )
@@ -334,12 +350,14 @@ func (h *ExtensionHost) SwitchToBestProfileAsync(reason string) {
334350 })
335351}
336352
337- // Backend returns the [Backend] used by the extension host .
338- func (h * ExtensionHost ) Backend () Backend {
353+ // SendNotifyAsync implements [ipnext.Host] .
354+ func (h * ExtensionHost ) SendNotifyAsync ( n ipn. Notify ) {
339355 if h == nil {
340- return nil
356+ return
341357 }
342- return h .b
358+ h .enqueueBackendOperation (func (b Backend ) {
359+ b .SendNotify (n )
360+ })
343361}
344362
345363// addFuncHook appends non-nil fn to hooks.
0 commit comments