fix(android): opening the vault no longer calls the server every time
Asked plainly by the user: why does open trigger a sync? Because OpenLocalNow displays the cache and then refreshes in the background, so a change made on the desktop shows up without anyone thinking about it. Sound intent, applied on EVERY open - including a lock followed by a re-open three seconds later, which cannot learn anything new. Measured cost of one such pointless refresh: 1 s of download and 5.5 s of key derivation. A minimum interval between two background refreshes fixes that, whatever else is wrong: the desktop does not publish several times a minute, and looking at most once a quarter of an hour is enough for a change to arrive unnoticed. Pressing Sync goes through another path and never waits. The sha comparison that should already have made an unchanged refresh cheap is still not firing - two fingerprints print identically yet compare unequal. It is now compared with SameText on trimmed values, which cannot confuse two distinct snapshots since a hex digest never differs by case or whitespace alone, and the log reports both lengths so the invisible character shows up on the next real refresh. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+34
-1
@@ -72,6 +72,19 @@ const
|
||||
// qu'un telephone repose ouvert.
|
||||
BACKGROUND_GRACE_SECONDS = 30;
|
||||
|
||||
// Duree minimale entre deux rafraichissements de fond.
|
||||
//
|
||||
// L'ouverture du coffre en declenchait un CHAQUE FOIS. Verrouiller puis
|
||||
// rouvrir trois secondes plus tard rappelait donc le serveur, qui ne pouvait
|
||||
// rien apprendre de neuf : un telechargement complet, et une derivation de
|
||||
// cle entiere des que l'empreinte ne concordait pas. Le poste ne publie pas
|
||||
// plusieurs fois par minute ; consulter au plus une fois par quart d'heure
|
||||
// suffit a ce que la modification arrive sans qu'on y pense.
|
||||
//
|
||||
// Ne concerne QUE le rafraichissement automatique. Un appui sur Sync passe
|
||||
// par un autre chemin et n'attend jamais.
|
||||
REFRESH_MIN_MINUTES = 15;
|
||||
|
||||
// FIRSTRUN_TOKEN et TEST_PWD viennent d'un fichier LOCAL, hors depot : le
|
||||
// jeton authentifie l'appareil, le mot de passe ouvre le coffre entier. Ni
|
||||
// l'un ni l'autre n'a sa place dans un depot, meme sans remote. Absents apres
|
||||
@@ -135,6 +148,8 @@ type
|
||||
FLastActivity: TDateTime;
|
||||
/// Quand l'application est passee derriere. 0 = elle est au premier plan.
|
||||
FBackgroundAt: TDateTime;
|
||||
/// Dernier rafraichissement de fond. 0 = jamais, donc le premier a lieu.
|
||||
FLastRefresh: TDateTime;
|
||||
procedure Touch;
|
||||
procedure OnIdleTimer(Sender: TObject);
|
||||
|
||||
@@ -629,8 +644,17 @@ begin
|
||||
// Afficher d'abord, synchroniser ensuite : le coffre est a l'ecran, le
|
||||
// reseau se debrouille derriere. Sans mot de passe range, on ne peut
|
||||
// rien ouvrir de nouveau - inutile d'aller voir.
|
||||
if FSyncPwd <> '' then
|
||||
if FSyncPwd = '' then
|
||||
Log(' no stored sync password - no background refresh')
|
||||
else if (FLastRefresh > 0) and
|
||||
(MinutesBetween(Now, FLastRefresh) < REFRESH_MIN_MINUTES) then
|
||||
Log(Format(' refreshed %d min ago - skipping (min %d)',
|
||||
[MinutesBetween(Now, FLastRefresh), REFRESH_MIN_MINUTES]))
|
||||
else
|
||||
begin
|
||||
FLastRefresh := Now;
|
||||
FetchAndDecrypt(FUrl, FToken, FSyncPwd, True);
|
||||
end;
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
@@ -880,6 +904,14 @@ begin
|
||||
end;
|
||||
|
||||
Log(' received ' + Length(LRes.Container).ToString + ' bytes');
|
||||
// LES DEUX EMPREINTES COTE A COTE. Sans cela on ne peut pas trancher
|
||||
// entre « le distant a change » et « la comparaison ne se declenche
|
||||
// pas », et les deux se ressemblent parfaitement de l'exterieur.
|
||||
// LES LONGUEURS AUTANT QUE LES VALEURS. Deux empreintes s'affichaient
|
||||
// identiques alors que l'egalite les separait : seul un caractere
|
||||
// invisible peut faire cela, et il ne se voit qu'au compte.
|
||||
Log(Format(' remote sha: %s (%d chars, known %d)',
|
||||
[LRes.ETag, Length(LRes.ETag), Length(FETag)]));
|
||||
|
||||
// LES COORDONNEES SONT RETENUES ICI, avant le dechiffrement. Un 200
|
||||
// avec un conteneur en main prouve l'adresse ET le jeton ; le mot de
|
||||
@@ -915,6 +947,7 @@ begin
|
||||
// Le mot de passe part avec le coffre : c'est lui qui permettra au
|
||||
// prochain lancement de rafraichir sans rien demander.
|
||||
SaveVault(LPlain, FETag, APwd, LCanAuth);
|
||||
Log(' cache now holds sha: ' + FETag);
|
||||
if VaultNeedsAuth then
|
||||
Log(' cache written - protected by biometrics/PIN')
|
||||
else if LCanAuth then
|
||||
|
||||
Reference in New Issue
Block a user