mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-04 15:49:49 +00:00
145 lines
2.8 KiB
Go
145 lines
2.8 KiB
Go
package download
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"sync"
|
|
|
|
internalblob "github.com/GopeedLab/gopeed/internal/blob"
|
|
"github.com/GopeedLab/gopeed/pkg/download/engine"
|
|
"github.com/GopeedLab/gopeed/pkg/download/engine/inject/stream"
|
|
enginewebview "github.com/GopeedLab/gopeed/pkg/download/engine/webview"
|
|
)
|
|
|
|
type engineSession struct {
|
|
engine *engine.Engine
|
|
|
|
mu sync.Mutex
|
|
refs int
|
|
closed bool
|
|
close []func()
|
|
}
|
|
|
|
func newEngineSession(e *engine.Engine) *engineSession {
|
|
return &engineSession{engine: e}
|
|
}
|
|
|
|
func (s *engineSession) SetEngine(e *engine.Engine) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.engine = e
|
|
}
|
|
|
|
func (s *engineSession) Retain() {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
if s.closed {
|
|
return
|
|
}
|
|
s.refs++
|
|
}
|
|
|
|
func (s *engineSession) Release() {
|
|
s.mu.Lock()
|
|
if s.refs > 0 {
|
|
s.refs--
|
|
}
|
|
shouldClose := s.refs == 0 && !s.closed
|
|
if shouldClose {
|
|
s.closed = true
|
|
}
|
|
s.mu.Unlock()
|
|
if shouldClose {
|
|
s.runClosers()
|
|
if s.engine != nil {
|
|
go s.engine.Close()
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *engineSession) CloseIfIdle() {
|
|
s.mu.Lock()
|
|
shouldClose := s.refs == 0 && !s.closed
|
|
if shouldClose {
|
|
s.closed = true
|
|
}
|
|
s.mu.Unlock()
|
|
if shouldClose {
|
|
s.runClosers()
|
|
if s.engine != nil {
|
|
s.engine.Close()
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *engineSession) OnClose(fn func()) {
|
|
if fn == nil {
|
|
return
|
|
}
|
|
s.mu.Lock()
|
|
if s.closed {
|
|
s.mu.Unlock()
|
|
fn()
|
|
return
|
|
}
|
|
s.close = append(s.close, fn)
|
|
s.mu.Unlock()
|
|
}
|
|
|
|
func (s *engineSession) runClosers() {
|
|
s.mu.Lock()
|
|
closeFns := s.close
|
|
s.close = nil
|
|
s.mu.Unlock()
|
|
for _, fn := range closeFns {
|
|
fn()
|
|
}
|
|
}
|
|
|
|
func (d *Downloader) newExtensionEngine() (*engine.Engine, *engineSession) {
|
|
session := newEngineSession(nil)
|
|
engineCfg := &stream.Config{
|
|
CreateObjectURL: func(opts *stream.ObjectURLOptions, open stream.ObjectURLOpener) (string, error) {
|
|
createOpts := &internalblob.CreateOptions{
|
|
Session: session,
|
|
}
|
|
if opts != nil {
|
|
createOpts.ContentType = opts.ContentType
|
|
createOpts.Size = opts.Size
|
|
createOpts.Range = opts.Range
|
|
}
|
|
return d.blob.CreateOpener(func(ctx context.Context, req internalblob.OpenRequest) (io.ReadCloser, error) {
|
|
return open(ctx, stream.ObjectURLOpenRequest{
|
|
Offset: req.Offset,
|
|
End: req.End,
|
|
})
|
|
}, createOpts)
|
|
},
|
|
RevokeObjectURL: func(url string) error {
|
|
return d.blob.Revoke(url)
|
|
},
|
|
}
|
|
e := engine.NewEngine(&engine.Config{
|
|
ProxyConfig: d.cfg.Proxy,
|
|
StreamConfig: engineCfg,
|
|
})
|
|
session.SetEngine(e)
|
|
return e, session
|
|
}
|
|
|
|
func (d *Downloader) newExtensionWebViewRuntime(session *engineSession) *enginewebview.Runtime {
|
|
var (
|
|
opener enginewebview.Opener
|
|
available bool
|
|
)
|
|
if provider := d.cfg.WebViewProvider; provider != nil && provider.IsAvailable() {
|
|
opener = provider
|
|
available = true
|
|
}
|
|
runtime := enginewebview.NewRuntime(opener, available)
|
|
session.OnClose(func() {
|
|
_ = runtime.Close()
|
|
})
|
|
return runtime
|
|
}
|