Zmiana implementacji WebView z Google/AOSP na Bromite w Androidzie

Spis treści

Przeglądając ostatnio opcje deweloperskie w swoim telefonie z Androidem 11, wpadła mi w oczy pozycja WebView implementation . Nie ukrywam, że trochę mnie ona zainteresowała i zacząłem się zastanawiać czym tak naprawdę jest ten cały WebView. Mój smartfon działa aktualnie pod kontrolą crDroid (ROM na bazie AOSP/LineageOS) i nie jest on sprzęgnięty z usługami od Google (brak jakichkolwiek GAPPS'ów). Dlatego też w tym przypadku w implementacji WebView widnieje w zasadzie tylko jedna opcja, tj. Android System WebView. W przypadku stock'owych ROM'ów producentów telefonów będziemy mieli zaś do czynienia z Google System WebView. Jakby nie patrzeć, zarówno Android/AOSP System WebView, jak i Google System WebView pochodzą od Google, który niezbyt troszczy się o naszą prywatność. W mojej głowie pojawiło się zatem pytanie na temat tego czym te dwie implementacje się od siebie różnią, no i naturalnie też czy są jakieś alternatywne implementacje WebView, z których można by skorzystać zastępując te domyślnie preinstalowane?

Co to jest WebView

WebView to taki mechanizm, z którego korzystają aplikacje Androida do generowania zawartości stron WWW. Zapewne każdy z nas spotkał się z taki appkami, które domyślnie otwierają linki w swoim obrębie, dając też opcję otwarcia takich stron w zewnętrznej przeglądarce internetowej. Za taką funkcjonalność właśnie odpowiada WebView, który umożliwia zaimplementowanie prostej przeglądarki internetowej wewnątrz danej aplikacji bez potrzeby pchania do niej całego kodu odpowiedzialnego za realizowanie renderowania kodu HTML. W ten sposób deweloperzy aplikacji mogą zająć się rozwijaniem samej aplikacji, a sprawy związane z renderowaniem stron WWW oddelegować do WebView. Każdy Android ma preinstalowany taki WebView domyślnie, choć jego implementacje mogą się naturalnie różnić.

W przypadku integracji ROM'u z usługami od Google, za implementacje WebView będzie robił Google System WebView (oparty na Chrome). W ten sposób każda strona WWW, która zostanie otworzona wewnątrz jakiejś aplikacji użytkownika, będzie otwierana w środowisku Google, przez co Google ma pełny wgląd w to, jakie witryny oglądamy i co na nich robimy. W zasadzie otworzenie takiej strony WWW niczym nie różni się w stosunku do wrzucenia jej do pełnowymiarowej przeglądarki Google Chrome, gdzie jesteśmy zalogowani, tj. mamy powiązane w niej konto Google.

W przypadku ROM'ów opartych na AOSP (np. LineageOS) bez integracji z usługami od Google, za WebView będzie robił Android System WebView, który jest implementacją opartą o otwartoźródłowego Chromium. Podobnie jak w przypadku Google System WebView, otworzenie strony w aplikacji, która korzysta z Android System WebView, będzie równoznaczne z renderowaniem jej w przeglądarce Chromium, przynajmniej w dużym uproszczeniu.

Czym się różni WebView Android/AOSP od Google

Jako, że WebView robi za silnik renderujący kod HTML, to kluczowe z perspektywy bezpieczeństwa jest, by ten mechanizm był aktualizowany dość często. W przypadku Google System WebView, aktualizacje są wypuszczane regularnie (bo mamy tutaj do czynienia ze zwykłą aplikacją, którą można pobrać przez sklep Google Play). Natomiast jeśli chodzi o Android/AOSP System WebView, to z tymi update'ami różnie bywa, bo trzeba tutaj zaktualizować cały firmware/ROM. Warto zatem się zastanowić w tym miejscu czy ten ROM, z którego aktualnie korzystamy, dostaje regularnie jakieś aktualizacje (zwykle wydawane w interwale miesięcznym) i jeśli od dłuższego czasu nie było takiego update, to z punktu widzenia bezpieczeństwa powinniśmy zainstalować ten WebView od Google.

Pomijając kwestię aktualizacji, wygląda na to, że te dwie implementacje WebView nie różnią się zbytnio od siebie, choć nie do końca wiadomo czy Google nie dokłada czegoś własnościowego do swojego WebView (różne są zdania na ten temat). Tak czy inaczej, rezygnacja z WebView AOSP/Google i zastąpienie jej inną implementacją może sprawić, że niektóre aplikacje nie będą działać poprawnie. Dla przykładu, przeglądarki wewnątrz aplikacji użytkownika mogą crash'ować na innych implementacjach WebView i jeśli doświadczamy takiego zachowania przy korzystaniu z nich, to trzeba będzie prawdopodobnie powrócić do Google/AOSP System WebView i raczej tej bariery nie przeskoczymy.

Czym jest Bromite

Android System WebView może i jest OpenSource ale w dalszym ciągu pochodzi od Google, a ten za bardzo nie troszczy się o prywatność swoich użytkowników. Sam WebView nie ma też żadnych opcji konfiguracyjnych, dzięki którym moglibyśmy dostosować ten aspekt przeglądania stron WWW wewnątrz konkretnych aplikacji. Trzeba zatem zdać się na łaskę Google w kwestii prywatności, tj. wszystkie informacje na temat naszej aktywności w takich aplikacjach korzystających z WebView będą przez Google zbierane. Takie zachowanie jest domyślnie włączone również w implementacji Android/AOSP System WebView, chyba, że twórca danego ROM'u ten ficzer wyłączył. Niemniej jednak, Google w dalszym ciągu może nas śledzić przez WebView za sprawą nadużywania nagłówka X-Requested-With i z tym za bardzo nie da się nic zrobić. Istnieje jednak inna implementacja WebView, tj. Bromite System WebView, która jest ukierunkowana właśnie na dostarczenie swoim użytkownikom maksimum prywatności.

Problem jednak w tym, że tego całego WebView nie da się od tak po prostu wymienić. Jest to bardzo kluczowy mechanizm i wręcz krytyczny pod względem bezpieczeństwa. Dlatego ta aplikacja rezyduje gdzieś w obrębie partycji /super/ (zwykle /system/ lub /product/ ), która w nowszych Androidach (10+) jest dostępna tylko i wyłącznie do odczytu. Z poziomu działającego systemu nie da rady tej partycji zamontować w trybie do zapisu. Dlatego też by zmienić implementację WebView, trzeba będzie mieć ukorzenionego Androida, tj. posiadać w nim prawa administratora systemu root.

Jak zmienić WebView od Google/AOSP na Bromite

Zgodnie z informacjami zawartymi na stronie projektu Bromite, jest kilka metod by zainstalować ich WebView. W moim przypadku żadna z tych instrukcji nie przyniosła jakiegoś wymiernego efektu. Zwykła próba zainstalowania arm64_SystemWebView.apk kończyła się niepowodzeniem. Można o tym problemie też poczytać na podlinkowanym wyżej wiki. Chodzi generalnie o to, że plik webview.apk rezyduje w obrębie partycji /system/ , no i też jest podpisany innym kluczem. Nie da rady zatem tej appki od tak sobie zainstalować w systemie, bo mechanizmy bezpieczeństwa nam na to zwyczajnie nie pozwolą. Próbowałem też wyłączyć stock'owy WebView przy pomocy tego poniższego polecenia:

$ adb shell "pm list packages | grep webview"
package:com.android.webview

$ adb shell "pm uninstall -k --user 0 com.android.webview"
Success

Oczywiście udało się tę aplikację wyłączyć ale w dalszym ciągu nie szło zainstalować WebView od Bromite. Przywróciłem zatem tę odinstalowaną appkę w poniższy sposób:

$ adb shell "cmd package install-existing com.android.webview"
Package com.android.webview installed for user: 0

Kompatybilność ROM'u z Bromite

Pomyślałem może, że mój Android nie jest jakoś specjalnie kompatybilny z Bromite, więc sprawdziłem, zgodnie z zaleceniem, co zwróci analiza pliku /system/framework/framework-res.apk (sygnatury w linijkach z C: zostały przycięte dla czytelności):

$ adb pull /system/framework/framework-res.apk
/system/framework/framework-res.apk: 1 file pulled. 14.7 MB/s (53618124 bytes in 3.490s)

$ aapt d xmltree framework-res.apk res/xml/config_webview_packages.xml
E: webviewproviders (line=18)
  E: webviewprovider (line=20)
    A: availableByDefault=(type 0x12)0xffffffff
    A: description="Google WebView" (Raw: "Google WebView")
    A: packageName="com.google.android.webview" (Raw: "com.google.android.webview")
    E: signature (line=21)
      C: "MIIDuzCC...g69H8l8M"
  E: webviewprovider (line=23)
    A: availableByDefault=(type 0x12)0xffffffff
    A: description="Google WebView Beta" (Raw: "Google WebView Beta")
    A: packageName="com.google.android.webview.beta" (Raw: "com.google.android.webview.beta")
    E: signature (line=24)
      C: "MIIFxzCC...UbGtPA=="
  E: webviewprovider (line=26)
    A: availableByDefault=(type 0x12)0xffffffff
    A: description="Google WebView Dev" (Raw: "Google WebView Dev")
    A: packageName="com.google.android.webview.dev" (Raw: "com.google.android.webview.dev")
    E: signature (line=27)
      C: "MIIFxzCC...9+p2OA=="
  E: webviewprovider (line=29)
    A: availableByDefault=(type 0x12)0xffffffff
    A: description="Google WebView Canary" (Raw: "Google WebView Canary")
    A: packageName="com.google.android.webview.canary" (Raw: "com.google.android.webview.canary")
    E: signature (line=30)
      C: "MIIFxzCC......hrFdCQ=="
  E: webviewprovider (line=34)
    A: availableByDefault=(type 0x12)0xffffffff
    A: description="AOSP WebView" (Raw: "AOSP WebView")
    A: packageName="com.android.webview" (Raw: "com.android.webview")

Zgodnie z wymaganiami, powinniśmy mieć tutaj packageName="com.android.webview" bez sygnatury i faktycznie, jak można wyżej zauważyć, przy tej ostatniej pozycji nie ma żadnej sygnatury. Zatem najwyraźniej nic nie stoi na przeszkodzie, by ten WebView wymienić.

Próba skorzystania z aplikacji /system/app mover

Próbowałem więc dalej i kolejnym sposobem było skorzystanie z appki /system/app mover. Ten sposób również okazał się bezowocny. Najwyraźniej appka /system/app mover jest przeznaczona dla starszych Androidów i próba przeniesienia aplikacji w Andku 11 z partycji systemowych na partycję /data/ nie daje żadnego efektu, a jedynie kończy się błędem Could not remount /system/ .

Brak katalogu /system/app/webview/

Niezniechęcony jednak brakiem wymiernych efektów, próbowałem dalej. Kolejnym sposobem było ręczne usunięcie pliku webview.apk z katalogu /system/app/webview/ . Niestety w przypadku ROM'u crDroid wgranego na mojego Xiaomi Redmi 9, taki katalog w ogóle nie istnieje. Nie poddałem się jednak tak łatwo i przy pomocy narzędzia find postanowiłem przeszukać cały flash telefonu w poszukiwaniu tego pliku, bo przecie gdzieś on być musi. No i znalazłem:

galahad:/ # find / -iname "*webview.apk"
...
/product/app/webview/webview.apk
...

Czyli webview.apk znajduje się tutaj nie pod /system/app/webview/ , a pod /product/app/webview/ , ot taka drobna różnica. Niemniej jednak, usunięcie tego pliku ze wskazanej wyżej lokalizacji też nie wchodzi w grę, bo system plików jest domyślnie zamontowany w trybie tylko do odczytu.

System plików tylko do odczytu

W Androidzie 11 mamy partycję /super/ , na którą składają się trzy inne partycje, tj. /system/ , /vendor/ oraz /product/ . Poszukałem zatem, które urządzenie odpowiada za tę partycję /product/ w celu przemontowania jej systemu plików w tryb do zapisu:

galahad:/ # mount | grep -i product
/dev/block/dm-2 on /product type ext4 (ro,seclabel,relatime)

Niby teraz wystarczyłoby przemontować tę partycję podając w mount flagę -o remount,rw ale (jak to zwykle bywa) taki zabieg się również nie powiódł:

galahad:/ # mount -o remount,rw /product/
mount: '/product/' not in /proc/mounts

galahad:/ # mount -o remount,rw /dev/block/dm-2
'/dev/block/dm-2' is read-only

Zaciągnięcie do pracy TWRP/SHRP

Trochę już zacząłem tracić cierpliwość i ostatnia rzecz, która wpadła mi do głowy, to odpalenie trybu recovery TWRP/SHRP. Tam były opcje montowania partycji systemowych w trybie do zapisu, w tym też tego nieszczęsnego /product/ . Problem natomiast był taki, że z menu SHRP nie szło tej partycji zamontować w trybie do zapisu, przynajmniej bezpośrednio z GUI. Ale od czego jest terminal? Sprawdziłem zatem czy jak ręcznie będę próbował przemontować partycję /product/ z poziomu recovery, to czy coś to da:

$ adb shell
lancelot:/ # mount | grep product
/dev/block/dm-2 on /product type ext4 (ro,seclabel,relatime)

lancelot:/ # mount -o remount,rw /product

No i proszę, nie ma żadnego błędu. Sprawdziłem jeszcze by się upewnić, że coś w tym katalogu w ogóle się znajduje i czy jest tam ten plik, o który się nam rozchodzi:

lancelot:/ # ls -al /product/app/webview/
total 159380
drwxr-xr-x  3 root root      4096 2009-01-01 00:00 .
drwxr-xr-x 19 root root      4096 2021-10-06 21:51 ..
drwxr-xr-x  4 root root      4096 2009-01-01 00:00 oat
-rw-r--r--  1 root root 163726925 2009-01-01 00:00 webview.apk

Backup webview.apk

Zatem wszystko wygląda dobrze. Postanowiłem na wszelki wypadek przenieść zarówno katalog oat/ jak i sam plik webview.apk na kartę SD (w razie czego będzie co przywrócić jakby się coś popsuło):

lancelot:/product/app/webview # mv webview.apk /external_sd/
lancelot:/product/app/webview # mv oat /external_sd/

Podmiana webview.apk na ten od Bromite

Mając backup pliku webview.apk możemy kontynuować z instalacją Bromite. Ze strony projektu pobieramy plik .apk. W tym przypadku jest to arm64_SystemWebView.apk . Wgrywamy go do katalogu /product/app/webview/ zmieniając mu naturalnie nazwę na webview.apk :

$ adb push arm64_SystemWebView.apk /sdcard/Download
arm64_SystemWebView.apk: 1 file pushed. 12.5 MB/s (86437563 bytes in 6.608s)

lancelot:/product/app/webview # mv /sdcard/Download/arm64_SystemWebView.apk ./webview.apk
lancelot:/product/app/webview # ls -al
total 84420
drwxr-xr-x  2 root     root     4096 2021-10-06 23:00 .
drwxr-xr-x 19 root     root     4096 2021-10-06 21:51 ..
-rw-r--r--  1 root     root 86437563 2021-10-06 21:45 webview.apk

Sprawdźmy też uprawnienia do tak wgranego pliku webview.apk , bo czasami mogą one nie być odpowiednie. Właściciel oraz grupa powinna wskazywać na root:root oraz prawa do pliku trzeba określić na 644 . Jeśli po wgraniu webview.apk któreś z tych powyższych rzeczy się różni, to trzeba te uprawnienia przepisać via chown/chmod .

lancelot:/product/app/webview # chown root:root webview.apk
lancelot:/product/app/webview # chmod 644 webview.apk

Na koniec montujemy partycję /product/ z powrotem w tryb do odczytu:

lancelot:/ # mount -o remount,ro /product

Z menu TWRP/SHRP czyścimy także cały cache, po czym restartujemy telefon:

lancelot:/ # reboot

Ponowna instalacja pliku .apk

Smartfon powinien uruchomić się bez problemu ale to nie wszystko co trzeba zrobić, by WebView od Bromite zainstalować w systemie. Trzeba jeszcze raz wgrać paczkę arm64_SystemWebView.apk , tym razem w zwyczajny sposób, tj. przez instalator Androida. Proces instalacji tej aplikacji powinien zakończyć się powodzeniem.

Sprawdzenie aktualnej implementacji WebView

Po procesie instalacyjnym wypadałoby jeszcze zweryfikować, czy aby na pewno przebiegł on tak jak należy. Wchodzimy zatem w ustawienia deweloperskie i sprawdzamy czy pod WebView implementation widnieje Bromite System WebView , tak jak na poniższym obrazku:

Jeśli mamy podobny wynik, to znaczy, że z powodzeniem udało nam się zastąpić implementację WebView od Google/AOSP tą od Bromite.

Aplikacja WebView Test

Warto też w tym miejscu dodać, że w sklepie Google Play jest dostępna aplikacja, która jest w stanie zweryfikować, czy aktualna implementacja WebView działa prawidłowo. Chodzi o appkę WebView Test. Wystarczy ją uruchomić i sprawdzić czy przykładowa strona WWW jest w stanie się w tej aplikacji bez problemu wyrenderować.

Jeśli tak, to znaczy, że wszystko jest w porządku.

W aplikacji WebView Test jest też możliwość zweryfikowania aktualnie wykorzystywanej wersji silnika WebView -- wystarczy z menu wybrać WebView Info :

Jak możemy zauważyć na powyższej fotce, w mamy tam sporo fraz z Chrome . Jest to intencjonalne zachowanie Bromite, który wykorzystuje szereg technik mających przeciwdziałać profilowaniu przeglądarki w oparciu o jej fingerprint. Dlatego też te informacje nie do końca pokrywają się ze stanem faktycznym i nie ma co do nich przykładać większej wagi. Kluczowa rzecz przy ustaleniu czy posiadamy WebView od Bromite, to obecność stosownej implementacji w ustawieniach deweloperskich.

Możemy też zrobić test oferowany przez Bromite w tej appce WebView Test. Powinniśmy uzyskać wynik 5/9:

Repozytorium F-Droid dla Bromite

Mając już wgrany Bromite System WebView, trzeba zatroszczyć się o jego regularną aktualizację. Manualne odwiedzanie strony projektu, pobieranie nowszej wersji pliku .apk i ręczna aktualizacja tej aplikacji nie jest zbyt wygodnym rozwiązaniem. Dlatego też Bromite oferuje swoje własne repozytorium, które możemy dodać do F-Droid. W ten sposób aktualizacja WebView będzie przebiegać o wiele sprawniej i szybciej.

Magisk i moduł WebView Switcher

Gdy już w zasadzie udało mi się ten WebView wymienić, to przez przypadek zauważyłem na liście modułów Magisk'a, że widnieje tam pozycja WebView Switcher . Z opisu wygląda na to, że ten moduł jest w stanie zrobić wszystkie te kroki poczynione wyżej ale bez wprowadzania żadnych zmian w partycji /system/ czy /product/ .

Postanowiłem zatem przywrócić wszystko na swoje miejsce i sprawdzić jak WebView Switcher sobie poradzi ze zmianą WebView w Androidzie mojego smartfona.

Po zainstalowaniu tego dodatku i uruchomieniu telefonu ponownie, wszystko zdaje się działać dokładnie w ten sam sposób, co został opisany powyżej, choć patrząc za webview w mount znalazłem jedynie te poniższe wpisy:

galahad:/ # mount | grep -i webview
/dev/HNTLL8/.magisk/block/data on /product/overlay/WebviewOverlay.apk type ext4 (rw,seclabel,relatime,nobarrier,noauto_da_alloc,inlinecrypt,resuid=10010,resgid=1065,errors=panic,data=ordered)
/dev/HNTLL8/.magisk/block/data on /system/app/BromiteWebview type ext4 (rw,seclabel,relatime,nobarrier,noauto_da_alloc,inlinecrypt,resuid=10010,resgid=1065,errors=panic,data=ordered)
/dev/HNTLL8/.magisk/block/system_root on /system/etc/permissions/android.software.webview.xml type ext4 (ro,seclabel,relatime)

Zatem wygląda na to, że BromiteWebview został wgrany do /system/app/ , a ten problematyczny plik webview.apk nie był w żaden sposób ruszony.

Podsumowanie

Osoby, którym zależy na prywatności w sieci, zwłaszcza w kontekście przeglądania stron WWW z poziomu swojego telefonu, powinny zainteresować się implementacją WebView, którą oferuje Bromite. Niestety nie wszędzie wymiana tego kluczowego komponentu Androida będzie wchodzić w grę, bo do tego celu potrzebne nam będą prawa root, a te z kolei nie są standardowo dostępne, gdy korzystamy z fabrycznego oprogramowania producenta smartfona. Trzeba też mieć na uwadze ewentualne problemy, które może ze sobą nieść wymiana silnika renderującego kod HTML, bo niektóre aplikacje mogą na innych implementacjach WebView nie działać prawidłowo. Póki co jednak, nie zdarzyło mi się, by appki, z których korzystam na co dzień (a jest ich dość sporo), zachowywały się w jakiś bliżej nieprzewidywalny sposób. Można zatem przyjąć, że w przypadku tych otwartoźródłowych aplikacji, problemów być raczej nie powinno.

Mikhail Morfikov avatar
Mikhail Morfikov
Po ponad 10 latach spędzonych z różnej maści linux'ami (Debian/Ubuntu, OpenWRT, Android) mogę śmiało powiedzieć, że nie ma rzeczy niemożliwych i problemów, których nie da się rozwiązać. Jedną umiejętność, którą ludzki umysł musi posiąść, by wybrnąć nawet z tej najbardziej nieprzyjemniej sytuacji, to zdolność logicznego rozumowania.