Poznajemy nieodłączne części przeglądarki internetowej. Pewne podsumowanie wielu różnych działów i coś, bez czego nie ruszymy do przodu. Do dzieła.

Ok, przypomnijmy sobie taki kod PHP:

<?php
echo $_SERVER['HTTP_USER_AGENT'] . "\n\n";

Co on nam zwraca? Cóż, pierwszy wynik to będzie Chrome, drugi to Firefox:

//Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
//Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0 

Na MDN jest cała dokumentacja, która opisuje ten string i co on oznacza. Możemy później, jak się nieco więcej dowiemy, wejść i nauczyć się o co chodzi.

Na razie wiemy dwie rzeczy:

  • HTTP, czyli ten USER_AGENT, to jest część protokołu HTTP, nagłówek przesyłany za pomocą tego protokołu
  • Skoro jest to nagłówek, to znaczy, że może być spoofowany, zatem nie jest to wiarygodne źródło informacji

W czasach, w których mieliśmy takie telefony od Windowsa (nie Android i nie Mac i wówczas najnowszy krzyk mody), gdy mniej było botów i scraperów, gdy mniej było responsywności i narzędzi do niej zaś przeglądarki na urządzeniach mobilnych posiadały kursor a touchpady to mogliśmy sobie oglądać co najwyżej na odtwarzaczach MP4…

W tamtych czasach najbardziej rozwojowi ludzie mający jakieś portale tworzyli ich mobilne, lżejsze wersje i było proxy na request każdej podstrony. I jeżeli wykryto w tym stringu, że wchodzisz z urządzenia mobilnego, to przekierowywało na wersję mobilną (szału człowiek mógł dostać, jak miał dobry internet, nie miał problemu z małą czcionką, ale chciał zobaczyć wersję niemobilną).

O proszę, mamy tutaj przykład z tamtych czasów. Także przykład, jak bardzo ludzie wtedy nie ogarniali dosłownie wszystkiego, z operatorami włącznie:

<?php
$iphone = strpos($_SERVER['HTTP_USER_AGENT'],"iPhone");
$android = strpos($_SERVER['HTTP_USER_AGENT'],"Android");
$palmpre = strpos($_SERVER['HTTP_USER_AGENT'],"webOS");
$berry = strpos($_SERVER['HTTP_USER_AGENT'],"BlackBerry");
$ipod = strpos($_SERVER['HTTP_USER_AGENT'],"iPod");

if ($iphone || $android || $palmpre || $ipod || $berry == true)
{
header('Location: http://mobile.site.com/');
//OR
echo "<script>window.location='http://mobile.site.com'</script>";
}
?>

No, tutaj mamy głupie sprawdzanie, czy berry == true, zaś w przypadku innych jest to po prostu sprawdzanie, czy są non-truthy.

To znaczy – ten operator porównania z true działa tylko na berry. Można go albo wywalić albo trzeba dopisać do każdej ze zmiennych. Ale za to cwaniak przez window.location chce przekierowywać.

Ok, inny przykład z tamtych czasów:

<?php
if(! empty($_SERVER['HTTP_USER_AGENT'])){
    $useragent = $_SERVER['HTTP_USER_AGENT'];
    if( preg_match('@(iPad|iPod|iPhone|Android|BlackBerry|SymbianOS|SCH-M\d+|Opera Mini|Windows CE|Nokia|SonyEricsson|webOS|PalmOS)@', $useragent) ){
        header('Location: ./mobile/');
    }
}
?>

StackOverflow prawie 12 lat temu. Ok, nieważne. Kiedyś to było wiarygodne źródło informacji, dzisiaj nie. Przykład z naszego bloga:

<?php
class DomDocumentParser {

	private $doc;

	public function __construct($url) {

		$options = array(
			'http'=>array('method'=>"GET", 'header'=>"User-Agent: scraperBot/0.1\n")
			);
		$context = stream_context_create($options);

		$this->doc = new DomDocument();
		@$this->doc->loadHTML(file_get_contents($url, false, $context));
	}

}

Tak, tutaj tworzyliśmy robota do scrapowania stron WWW w czystym PHP bez biblioteczek. I ten User-Agent nadawaliśmy.

Znaczy – każdy to może nadpisać. PHP niby posiada funkcję get_browser, ale raz, że nie działa jak należy, dwa że bazuje na tym stringu.

W ramach ćwiczenia polecam poszukać github w poszukiwaniu malware napisanego w JS, które wykrywa jakiej przeglądarki i jakiej wersji używamy. Wiele się nauczymy.

Ale ja nie o tym. Z czego składa się przeglądarka, to nasz temat.

Ok, jest kilka elementów:

  • JavaScript Engine
  • Rendering Engine
  • UI Backend
  • Storage
  • Inne głupoty, aby program działał

Ok, co to JavaScript engine? To rzecz, która zamienia JS na kod maszynowy, analiza leksykalna, tokenizacja, AST, egzekucja kodu. I tylko to, dlatego JS engine jest też częścią JavaScriptowych rzeczy, nie będących przeglądarkami (jak node).

Jakie mamy JS engines:

  • V8 – Chrome oraz node.js (który przeglądarką nie jest, ale mechanizm zamieniania składni JS na kod wykorzystuje)
  • Chakra – Microsoft Edge
  • Spider Monkey – Mozilla Firefox
  • Webkit – Safari

Ok, czyli JS engine się tym zajmuje. Mało tego, JS engine NIE POSIADA pętli zdarzeń. Pętla zdarzeń to biblioteka libuv. Częścią node.js jest V8 (także używany przez Chrome) oraz libuv (także używany przez Chrome i wszystkie inne przeglądarki).

Ok, a co to jest Rendering Engine? Już się domyślamy, że rendering engine będzie TYLKO w przeglądarkach, coś co operuje JSem, ale nic nie wyświetla (jak node) tego nie potrzebuje.

Dokładnie tak, to jest engine przeglądarki służący do renderowania elementów strony w oparciu o DOM i CSSOM, który tworzy Render Tree. I są tam różne fazy, które poznamy lepiej, które koniec końców renderują nam stronę WWW.

Ok, rendering engines:

  • Blink (Chrome)
  • WebKit (Safari)
  • Gecko (Mozilla)
  • Trident (Microsoft Edge)

I tak wygląda rendering engine. Takie coś, jak node.js tego nie potrzebuje, potrzebuje za to JS Engine (v8) oraz pętlę zdarzeń (libuv).

Ok, co jeszcze ma przeglądarka? Storage, czyli cookies, indexdb, inne głupoty, cache, ogólnie interfejs przeglądarki i jakieś takie rzeczy, które sprawiają, że to wszystko działa, jak każda aplikacja GUI.

Ma też Backend UI, czyli coś, co wyświetla różne podstawowe widgety (elementy strony) takie jak button, form i tym podobne. Być może zauważyliśmy, że na tej samej przeglądarce, ale różnych systemach operacyjnych mogą być drobne zmiany.

Albo na tym samym systemie operacyjnym, ale innych przeglądarkach też różne rzeczy odrobinę inaczej wyglądają. Mimo wszystko wypełniają pewien standard zapewnienia pewnych elementów, które jednakowo są zapisywane w HTML.

Ok, co jeszcze może mieć przeglądarka? Poza całym backendem jej, czyli wykonywaniem requestów, pobieraniem i zapisywaniem, bla bla bla, i poza tym wszystkim, co już opisaliśmy, przeglądarka ma jeszcze swoje własne API, eksperymentalne ficzery (które potem może starać się wprowadzić do ogólnego standardu), rozszerzenia, które pozwala pisać i dodawać i cokolwiek jeszcze zechce.

Tym niemniej, tak wygląda przeglądarka internetowa…