mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-14 05:49:02 +02:00
fix(download): prepare fallback sessions before availability checks
This commit is contained in:
@@ -690,7 +690,18 @@ func DownloadWithExtensionFallback(req DownloadRequest) (*DownloadResponse, erro
|
||||
|
||||
provider := newExtensionProviderWrapper(ext)
|
||||
|
||||
availability, err := provider.CheckAvailabilityForItemID(req.ISRC, req.TrackName, req.ArtistName, req.SpotifyID, req.DeezerID, req.TidalID, req.QobuzID, req.DurationMS, req.ItemID, extensionAvailabilityTrackContext(req))
|
||||
// Fallback providers need the same session preparation as the selected
|
||||
// provider. A cached availability result may never call signedFetch,
|
||||
// leaving an expired session or pending challenge invisible to the app.
|
||||
var availability *ExtAvailabilityResult
|
||||
verificationRequired, err := preflightExtensionDownloadSession(providerID)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("signed-session preflight failed: %w", err)
|
||||
} else if verificationRequired {
|
||||
err = fmt.Errorf("verification_required: extension '%s' needs signed-session verification", providerID)
|
||||
} else {
|
||||
availability, err = provider.CheckAvailabilityForItemID(req.ISRC, req.TrackName, req.ArtistName, req.SpotifyID, req.DeezerID, req.TidalID, req.QobuzID, req.DurationMS, req.ItemID, extensionAvailabilityTrackContext(req))
|
||||
}
|
||||
if shouldAbortCancelledFallback(req.ItemID, err) {
|
||||
return nil, ErrDownloadCancelled
|
||||
}
|
||||
@@ -713,7 +724,7 @@ func DownloadWithExtensionFallback(req DownloadRequest) (*DownloadResponse, erro
|
||||
}, nil
|
||||
}
|
||||
} else {
|
||||
GoLog("[DownloadWithExtensionFallback] %s: not available\n", providerID)
|
||||
GoLog("[DownloadWithExtensionFallback] %s: not available (reason: %s)\n", providerID, resolveExtensionAvailabilityReason(availability, nil))
|
||||
}
|
||||
if terminalAvailability {
|
||||
GoLog("[DownloadWithExtensionFallback] %s requested skip_fallback after availability check\n", providerID)
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func TestFallbackKeepsPendingVerificationOwnership(t *testing.T) {
|
||||
for _, mode := range []string{"fresh-response", "saved-challenge", "network-error", "download-error", "empty-download-error"} {
|
||||
for _, mode := range []string{"fresh-response", "saved-challenge", "cached-unavailable", "cold-session", "network-error", "download-error", "empty-download-error"} {
|
||||
t.Run(mode, func(t *testing.T) {
|
||||
primary := newTestLoadedExtension(t, ExtensionTypeDownloadProvider)
|
||||
primary.ID, primary.Manifest.Name = "primary-provider", "primary-provider"
|
||||
@@ -41,6 +41,7 @@ func TestFallbackKeepsPendingVerificationOwnership(t *testing.T) {
|
||||
registerExtension({
|
||||
searchTracks: queryCatalog,
|
||||
checkAvailability: function() {
|
||||
if (fixtureMode === "cached-unavailable" || fixtureMode === "cold-session") return {available: false, reason: "No verified track match found"};
|
||||
if (fixtureMode === "network-error") throw new Error("lookup network timeout");
|
||||
if (fixtureMode === "download-error" || fixtureMode === "empty-download-error") return {available: true, track_id: "matched-track"};
|
||||
if (fixtureMode === "saved-challenge") throw savedChallenge;
|
||||
@@ -89,13 +90,16 @@ func TestFallbackKeepsPendingVerificationOwnership(t *testing.T) {
|
||||
Body: io.NopCloser(strings.NewReader(`{"auth_url":"https://auth.example.test/verify"}`)),
|
||||
}, nil
|
||||
})}
|
||||
expectsVerification := mode == "fresh-response" || mode == "saved-challenge"
|
||||
if expectsVerification {
|
||||
expectsVerification := mode == "fresh-response" || mode == "saved-challenge" || mode == "cached-unavailable" || mode == "cold-session"
|
||||
if expectsVerification && mode != "cold-session" {
|
||||
_, err := newExtensionProviderWrapper(secondary).SearchTracks("Song Artist", 1)
|
||||
if err == nil || GetPendingAuthRequest(secondary.ID) == nil {
|
||||
t.Fatalf("metadata lookup did not create a pending challenge: %v", err)
|
||||
}
|
||||
}
|
||||
if !expectsVerification {
|
||||
saveUsableSignedSession(t, secondary.runtime, *secondary.Manifest.SignedSession, "authenticated-session")
|
||||
}
|
||||
if err := last.ensureRuntimeReady(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -128,8 +132,8 @@ func TestFallbackKeepsPendingVerificationOwnership(t *testing.T) {
|
||||
if laterCalls.Load() != 0 || bootstrapCalls.Load() != 1 {
|
||||
t.Fatalf("pending challenge was skipped or recreated: later=%d bootstrap=%d", laterCalls.Load(), bootstrapCalls.Load())
|
||||
}
|
||||
} else if laterCalls.Load() != 1 {
|
||||
t.Fatal("ordinary lookup failures must allow the next provider")
|
||||
} else if laterCalls.Load() != 1 || bootstrapCalls.Load() != 0 {
|
||||
t.Fatalf("authenticated failures must allow fallback without bootstrapping: later=%d bootstrap=%d", laterCalls.Load(), bootstrapCalls.Load())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user