Steven
Steven5 perc olvasás

A Mac-alkalmazásod megkapja a mikrofon-hozzáférést — aztán minden indításkor elfelejti

A GeekBye mikrofonengedélyt kért, megadtad, és működött. A következő indításnál: eltűnt. És az alkalmazás egyáltalán meg sem jelent a Rendszerbeállítások → Mikrofon alatt. A bűnös egy macOS biztonsági funkció volt, amely csendben egy eltűnő elérési útról futtatta az alkalmazást — íme a diagnózis és az egyetlen kérdéssel megoldó javítás.

macOS
Engedélyek
Mérnöki munka
GeekBye kiadások
A Mac-alkalmazásod megkapja a mikrofon-hozzáférést — aztán minden indításkor elfelejti

Íme egy hiba, amitől kételkedni kezdesz a saját szemedben. Telepíted a GeekBye-t, mikrofon-hozzáférést kér, rákattintasz az Allow gombra, és az átírás működik. Remek. Kilépsz, másnap reggel újranyitod — és megint mikrofon-hozzáférést kér. Elmész megnézni a Rendszerbeállítások → Adatvédelem és biztonság → Mikrofon menüt, hogy kézzel javítsd, és a GeekBye nincs is a listán. Nem letiltva. Nem engedélyezve. Egyszerűen hiányzik, mintha sosem kérte volna.

Minden egyes darab helyesnek tűnt. A kérés valódi volt. Az engedély abban a pillanatban működött. Az alkalmazás megfelelően alá volt írva és notarizálva, a helyes használati szövegekkel. És az engedély mégis elpárolgott minden indításkor. A GeekBye v2.0.6 megjavította — és a kiváltó ok az egyik legalattomosabb dolog, amit a macOS a védelmed érdekében tesz.

A funkció, amely önmaga elől rejtette az alkalmazást

A bűnös a macOS App Translocation, egy Gatekeeper biztonsági funkció. Amikor letöltesz egy alkalmazást, és közvetlenül a DMG-ből vagy a ~/Downloads mappádból futtatod — bárhonnan, ahol még „karanténban" van —, a macOS valójában nem onnan futtatja, ahol látod. Átlátszóan átmásolja egy véletlenszerű, csak olvasható elérési útra, mélyen a /private/var/folders/.../AppTranslocation/… alá, és azt a másolatot futtatja. Jó védelem: megakadályozza, hogy egy rosszindulatú letöltés a mellette lévő fájlokat manipulálja.

De itt az ütközés. A macOS engedélyrendszere (a TCC — az, amelyik nyomon követi, ki használhatja a mikrofonod, kamerád, képernyőd) az alkalmazást az elérési útja és kódidentitása alapján azonosítja. Amikor az alkalmazás transzlokált, ez az elérési út véletlenszerű és ideiglenes. Így amikor mikrofon-hozzáférést adsz, a macOS engedelmesen rögzíti a megadást — egy olyan elérési úthoz, amely a következő indításkor nem fog létezni. Újranyitod az alkalmazást, a macOS egy másik véletlenszerű elérési útra transzlokálja, olyan alkalmazást lát, amelyről semmilyen feljegyzése nincs, és újra kérdez. És mivel az a fantom elérési út sosem stabil hely, az alkalmazás sosem szerez állandó sort a Rendszerbeállítások → Mikrofon alatt.

Az alkalmazás egy szellemnek adott engedélyt.

Ezért is történt, hogy csak néhány ember találkozott vele. Ha a GeekBye példányod már az /Applications mappában lakott — mert odahúztad, vagy mert automatikus frissítéssel oda került —, nincs karantén, nincs transzlokáció, stabil elérési út, és minden tökéletesen megmarad. A hiba láthatatlan volt számunkra és bárki számára, aki túl volt az első telepítésen, pontosan az a fajta hiba, amely a legtovább túléli.

A javítás: adj az alkalmazásnak igazi otthont

Mivel az egész probléma egy instabil elérési út, a javítás az, hogy az alkalmazást egy stabilra tesszük. A v2.0.6 észleli, amikor a GeekBye transzlokáltan fut (vagy egyszerűen az /Applications mappán kívülről fut), és egykattintásos „Move to Applications" lehetőséget kínál — a macOS áthelyezési hívásával, amely bemásolja a bundle-t az /Applications mappába, és onnan indítja újra. Ettől a ponttól kezdve az alkalmazásnak rögzített identitása van: a mikrofonengedély megmarad, a képernyőfelvétel megmarad, és a GeekBye végre megjelenik a Rendszerbeállításokban, ahol számítasz rá.

A kérés udvarias ezzel kapcsolatban. Felkínálja a Move to Applications, a Not Now és a Don't Ask Again lehetőséget — és megjegyzi az utolsó választást, így az alkalmazás sosem zaklat olyasvalakit, akinek szándékos oka van máshonnan futtatni. Annak eldöntése, hogy egyáltalán megjelenítse-e a kérést, kis, tiszta függvényekbe van izolálva (transzlokált-e ez a build? az /Applications mappán kívül van? elnyomta-e a felhasználó?), így a logikát unit-tesztelni lehet anélkül, hogy valódi notarizált buildet kellene elindítani egy valódi karanténba helyezett köteten.

Ugyanez a kiadás magát az engedélyélményt is leegyszerűsítette. A GeekBye korábban egy egyedi, testreszabott, alkalmazáson belüli engedélyablakot dobott fel — néhány száz sornyi UI, amely valamit próbált reprodukálni, amit az operációs rendszer már jól csinál. A v2.0.6 törölte ezt, és a natív macOS engedélykérésre támaszkodott, amelyet egy csendes, nem blokkoló szalag támogat, amely csak akkor jelenik meg, amikor egy szükséges engedély valóban hiányzik. Kevesebb kód, és olyan viselkedés, amelyet a felhasználók már felismernek, mert minden más Mac-alkalmazás ugyanígy működik.

A rész, amire a legbüszkébb vagyok: bebizonyítottuk, mielőtt elhittük

Könnyű lett volna megtippelni a transzlokációt, és kiadni egy javítást. Ehelyett a kiadás először egy indítási diagnosztikát hozott: indításkor a GeekBye most jelenti a saját futtatható fájljának elérési útját, és hogy transzlokált-e, hogy az /Applications mappán belül van-e, valamint a mikrofon- és képernyőengedélyek aktuális állapotát. Ez a telemetria egy hihető elméletet megerősítetté tett — a produkciós adatok megmutatták, hogy az érintett munkamenetek valóban az /Applications mappán kívüli transzlokált elérési utakról futottak, pontosan a jóslat szerint.

Ez a sorrend számít. A „megjelenik a kérés, de az engedély nem marad meg" mögött több lehetséges magyarázat áll — aláírási probléma, hiányzó használati szöveg, entitlement-gond, TCC-adatbázis furcsaság. Kizártuk az API-szintű okokat (a kérés útja bizonyíthatóan helyes volt), majd hagytuk, hogy a valós adatok az identitás/elérési út rétegre mutassanak, ahelyett, hogy egy reménykedő javítást adtunk volna ki, és reménykedtünk volna, hogy a támogatási jegyek elapadnak.

Három dolog, amit ez a hiba tanít

  1. Egy engedély, amely kér, de nem marad meg, identitás-probléma, nem API-probléma. Ha a kérés kódja helyes, és az engedély mégis eltűnik, hagyd abba a kérés újraírását. Kérdezd meg, milyen elérési úthoz és kódidentitáshoz köti az operációs rendszer a megadást — és hogy ez az identitás stabil-e az indítások között.
  2. Add ki a diagnosztikát a javítással együtt (vagy előtte). Néhány mező — honnan futok, mi az engedélyeim állapota — egy megalapozott találgatást igazolt kiváltó okká változtatott, és pontosan megmondta, mely felhasználók érintettek. Műszerezd fel a határt, amelyre gyanakszol, mielőtt megfoltoznád.
  3. A fejlesztők elől rejtőző hibák azok, amelyek a „rossz" környezetben futnak. A miénk minden fejlesztőgépen az /Applications mappában lakott, így a hiba szerkezetileg láthatatlan volt számunkra, miközben az első telepítésű felhasználókat sújtotta. Amikor egy bejelentés nem reprodukálható, az első kérdés az, hogy mi különbözik abban, ahol fut, nem az, hogy téved-e a felhasználó.

A GeekBye v2.0.6 az áthelyezési kérést és a diagnosztikát együtt adta ki. A tágabb megbízhatósági ívről, amelybe ez illeszkedik, lásd mit igényel valójában egy 2-es verzió (v2.0.0) és miért a rossz monitort rögzíti a képernyőfelvétel (v2.0.10) — egy másik hiba, amely csak egy adott környezetben bukkant fel. A szomszédos, apró részletekről szóló kiadásért lásd nyugodt szoftver: a villódzásjavítás és a válaszmód-chip (v2.0.3 + v2.0.5).

Kapcsolódó cikkek

Megkülönböztetni egy hívást egy nyitott alkalmazástól
Steven
Steven8 perc olvasás

Megkülönböztetni egy hívást egy nyitott alkalmazástól

A GeekBye észreveheti, hogy csatlakoztál egy videohíváshoz, és felajánlhatja, hogy rögzíti. Az észlelés a könnyebbik felének bizonyul — egy Swift bináris, amely tízmásodpercenként ablakcímeket olvas. A nehezebbik fél a pontosság: nem elsülni, amikor a Zoom csak nyitva van, nem rákérdezni egy megbeszélésre, amelyet már rögzítesz, és nem némítani a mikrofont abban a hívásban, amelyben valójában benne vagy. Három kiadás, és mindegyik egy védelem, amelynek meg kellett tanulnia, hogy ne győzze le önmagát.

Mérnöki munka
macOS
Desktop
A csend teherhordó volt
Steven
Steven7 perc olvasás

A csend teherhordó volt

A GeekBye v1 utolsó két kiadása ugyanarról a kényelmetlen igazságról szól: a valós idejű átírás egy valódi hálózaton nem veszteségmentes, és az őszinte lépés az, hogy abbahagyod az úgy tenni, mintha az lenne. A v1.8.20 minden audio chunk másolatát a lemezen tartotta, mielőtt egy újracsatlakozás során eldobta volna, és elkezdte hangosan megjelölni a réseket az átiratban. A v1.9.0 abbahagyta a csend küldését, hogy sávszélességet spóroljon — és felfedezte, hogy a csend pontosan az a jel volt, amelyet az átíró használt annak megállapítására, hogy egy mondat véget ért. Két kiadás a dolgok eldobásának költségéről.

Mérnöki munka
Audio
Megbízhatóság
A három ige, amely életben tartja a Web Audiót
Steven
Steven8 perc olvasás

A három ige, amely életben tartja a Web Audiót

Két GeekBye pontkiadás, két hónap eltéréssel és két különböző fájlban, ugyanarra a leckére tanította meg az audio kódunkat ellentétes végekről: ne kezeld a böngésző AudioContext-jét eldobhatóként. Az egyik kiadás megtanult resume()-t hívni egy contexten, amelyet a macOS csendben suspendelt a felvétel közepén; a másik megtanult suspend()-et hívni close() helyett, hogy az egymást követő munkamenetek ne csapódjanak bele a Chromium nagyjából hat contextes plafonjába. Resume, suspend, close — ez az egész cselekmény.

Mérnöki munka
Audio
Desktop