Що насправді відбувається, коли користувач забиває в браузер адресу google.com



Ця стаття є спробою відповіді на старе питання для співбесіди: «Що ж трапляється, коли ви друкуєте в адресному рядку google.com і натискаєте Enter?» Ми спробуємо розібратися в цьому максимально докладно, не пропускаючи ні однієї деталі.

Примітка: публікація заснована на зміст репозиторію What happens when...

Представлений контент рясніє великою кількістю термінів, переведення деяких з них можуть бути присутніми різні неточності. Якщо ви виявите якусь помилку в нашому перекладі   напишіть особистим повідомленням, і  все виправимо.

1. Натиснута клавіша «g»
Далі в статті міститься інформація про роботі фізичної клавіатури і переривання операційної системи. Але багато чого відбувається і крім цього — коли ви натискаєте клавішу «g», браузер отримує подія і запускається механізм автопідстановки. У залежно від алгоритму браузера і його режиму (включена функція «інкогніто») випадаючому вікні під рядком URL користувачеві буде запропоновано певну кількість варіантів для автопідстановки.

Більшість алгоритмів автопідстановки ранжирують рекомендації залежно від історії пошуку і залишених закладках. Деякі браузери (наприклад, Opera) навіть пропонують профілі друзів на Facebook. Коли користувач планує надрукувати в адресному рядку «google.com» нічого з перерахованого вище не грає ролі, але  менш виконається велику кількість коду, а рекомендації будуть оновлюватися з кожної нової надрукованій буквою. Можливо, запропонує перейти браузер на google.com до того, як користувач вб'є адресу

2. Клавіша «enter» натиснута до кінця
У якості певної нульової точки можна вибрати момент, коли клавіша Enter на клавіатурі натиснута до кінця і перебуває в нижньому положенні. У цій точці замикається електричний ланцюг цієї клавіші невелика кількість струму відправляється електросхемі клавіатури, яка сканує стан кожного перемикача клавіші перетворює сигнал в цілочисельний код клавіші (в даному випадку — 13). Потім контролер клавіатури конвертує код клавіші для передачі його комп'ютера. Як правило, зараз відбувається передача через USB або Bluetooth, а раніше клавіатура підключалася до комп'ютера з допомогою конекторів PS/2 або ADB.

 у разі USB-клавіатури:

  • Для роботи USB-контуру клавіатури потрібно 5 вольт харчування, які надходять через USB-контролер на комп'ютері.
  • Згенерований код клавіші зберігається в регістрі внутрішньої пам'яті клавіатури, який називається «кінцевою точкою» (endpoint).
  • USB-контролер комп'ютера опитує цю кінцеву точку кожні 10 мікросекунд і отримує зберігається там код клавіші.
  • Виберіть це значення надходить в USB SIE (Serial Interface Engine) для конвертації в один або більше USB-пакетів, які формуються за низкорівневому протоколом USB.
  • Ці пакети потім пересилаються з допомогою різних електричних сигналів через D+ і D — контакти з максимальною швидкістю 1,5 Мб/сек   оскільки HID-пристрої (Human Interface Device) завжди були «низькошвидкісними».
  • Цей послідовний далі сигнал декодується в USB-контролері комп'ютера і інтерпретується універсальним драйвером HID-пристроїв (клавіатури). Потім значення коду клавіші передається на «залізний» рівень абстракції операційної системи.
 у разі віртуальної клавіатури (тачскрін):

  • Коли користувач прикладає палець до сучасному ємкісному тач-екрану, невелику кількість струму передається до пальцю. Це замикає ланцюг через електростатичне поле провідного шару і створює падіння напруги в цій точці екрану. Екранний контролер потім ініціює переривання, повідомляє координату «кліка».
  • Потім мобільна ОС сповіщає поточне відкрите додаток про події кліка в одному з GUI-елементів (в цьому випадку   кнопках віртуальної клавіатури).
  • Віртуальна клавіатура викликає програмне переривання для відправки повідомлення «натиснута клавіша» назад в ОС.
  • Це переривання сповіщає поточне відкрите додаток про виникненні події натискання клавіші».

2.1 Виникло переривання [не для USB-клавіатур]

Клавіатура посилає сигнали в свою «лінію запитів переривань» (IRQ), яка потім порівнюється з «вектором переривання» (ціле число) контролером переривань. Процесор використовує таблицю дескрипторів переривань» (IDT) для зіставлення векторів переривань з функціями («обробники переривань») ядра. Коли з'являється переривання, процесор (CPU) оновлює IDT вектором переривання і запускає відповідний обробник. Таким чином, в справу вступає ядро.

2.2 (На Windows) Повідомлення
WM_KEYDOWN
відправлено додатком

HID передає подія натиснутою клавіші драйверу
KBDHID.sys
, який конвертує його в скан-код (scancode). У даному конкретному випадку скан-код  
VK_RETURN
(
0x0D
). Драйвер
KDBHID.sys
зв'язується з драйвером
KBDCLASS.sys
(драйвер класів клавіатури). Він відповідає за безпечну обробку всього вводу з клавіатури. У надалі цей драйвер викликає
Win32K.sys
(після можливої передачі повідомлення через встановлені сторонні клавіатурні фільтри). Все це відбувається в режимі ядра.

Win32K.sys визначає, яке вікно активно даний момент, з допомогою функції
GetForegroundWindow()
. Цей API забезпечує обробку вікна адресного рядка в браузері. Потім головний «насос повідомлень Windows викликає
SendMessage(hWnd, WM_KEYDOWN, VK_RETURN, lParam)
.
lParam
— це бітова маска, яка вказує на подальшу інформацію про натисканні клавіші: лічильник повторів (в цьому випадку 0), актуальний скан-код (може залежати від OEM, але
VK_RETURN
зазвичай не залежить від цього), інформацію про , чи натиснуті додаткові клавіші (наприклад, Alt, Shift, Ctrl   нашому випадку не були) і деякі інші дані.

У API Windows є функція
SendMessage
, яка поміщає повідомлення у чергу для конкретного обробника вікон (
hWnd
). Після цього для обробки всіх повідомлень черзі викликається головна функція обробки повідомлень (
WindowProc
), присвоєна обробникові
hWnd
.

Вікно (
hWnd
), активне даний момент, являє себе контрол обробки і в цьому випадку у WindowsProc є обробник повідомлень
WM_KEYDOWN
. Цей код вивчає третій параметр, який вступив в
SendMessage (wParam)
та, оскільки це
VK_RETURN
, розуміє, що користувач натиснув клавішу ENTER.

2.3 (В OS X) Подія
NSEVent KeyDown
відправлено додатком

Сигнал переривання активує подія переривання драйвері I/O Kit клавіатури. Драйвер переводить сигнал в код клавіатури, який потім передається процесу OS X під назвою
WindowServer
. У результаті,
WindowsServer
передає подія будь-якого придатного (активному або «хто слухає») додатком через Mach-порт, в якому подія поміщається в чергу. Потім події можуть бути прочитані з цієї черги потоками з достатніми привілеями, щоб викликати функцію
mach_ipc_dispatch
. Найчастіше це відбувається і обробляється з допомогою основного циклу
NSApplication
через
NSEvent
на
NSEventype KeyDown
.

2.4 (В GNU/Linux) Сервер Xorg слухає клавіатурні коди

У у разі графічного X server, для отримання натискання клавіші буде використаний загальний драйвер подій
evdev
. Перепризначення клавіатурних кодів скан-кодів здійснюється з допомогою спеціальних правил і карт X Server. Коли маппінг скан-код натиснутої клавіші завершено, X server посилає символ window manager (DWM, metacity, i3), який потім відправляє його в активне вікно. Графічний API вікна, отримав символ, друкує відповідний символ шрифту в потрібному полі.

3. Парсинг URL
Тепер у браузера є наступна інформація про URL:

Protocol «HTTP»
Використовувати «Hyper Text Transfer Protocol»

Resource «/»
Показати головну (індексного) сторінку

3.1 Це URL або пошуковий запит?

Коли користувач не запроваджує протокол або доменне ім'я, то браузер «згодовує» те, що людина надрукував, пошуковою машиною, встановленої за замовчуванням. Часто до URL додається спеціальний текст, який дозволяє пошуковій машині зрозуміти, що інформація передана з URL-рядок певного браузера.

3.2 Список перевірки HSTS

  • Браузер перевіряє список «предзагруженных HSTS (HTTP Strict Transport Security)». Це список сайтів, які вимагають, щоб до них зверталися лише за HTTPS.
  • Якщо потрібний сайт є в цьому списку, браузер посилає запит через HTTPS, а не HTTP. У іншому випадку, початковий запит надсилається за HTTP. (При цьому сайт може використовувати політику HSTS, але не перебувати в списку HSTS   в у такому випадку на перший запит по HTTP буде відправлено відповідь про те, що необхідно надсилати запити HTTPS. Однак це може зробити користувача вразливим до downgrade-атак   щоб цього уникнути, в браузери і включають список HSTS).

3.3 Конвертація не-ASCII Unicode символів в назва хосту

  • Браузер перевіряє ім'я хоста на наявність символів, відмінних від
    a-z
    ,
    A-Z
    ,
    0-9
    , або
    .
    .
  •  у разі доменного імені google.com ніяких проблем не буде, але якщо б домен містив не-ASCII символи, то браузер б застосував кодування Punycode для цієї частини URL.
4. Визначення DNS
  • Браузер перевіряє наявність домену своєму кеші.
  • Якщо домену там немає, то браузер викликає бібліотечну функцію
    gethostbyname
    (відрізняється різних ОС) для пошуку потрібної адреси.
  • Перш, ніж шукати домен DNS
    gethostbyname
    намагається знайти потрібну адресу в файлі
    hosts
    (його розташування відрізняється різних ОС).
  • Якщо домен ніде не закешований і відсутня в файлі
    hosts
    ,
    gethostbyname
    відправляє запит до мережного DNS-сервера. Як правило, це локальний роутер або DNS-сервер інтернет-провайдера.
  • Якщо DNS-сервер тієї підмережі, то ARP-запит відправляється цього сервера.
  • Якщо DNS-сервер інший підмережі, то ARP-запит відправляється на IP-адресу шлюзу за замовчуванням (default gateway).

4.1 Процес відправки ARP-запиту

Для того, щоб відправити широкомовний ARP-запит необхідно відшукати цільової IP-адресу, а також знати MAC-адреса інтерфейсу, який буде використовуватися для відправки ARP-запиту.

Кеш ARP перевіряється для кожного цільового IP-адреси — якщо адреса є в кеші, то бібліотечна функція повертає результат:
Target IP = MAC
.

Якщо ж записи в кеші немає:

  • Перевіряється таблиця маршрутизації — це робиться для того, щоб дізнатися, чи є шуканий IP-адресу в який-небудь з підмереж локальної таблиці. Якщо він там, то запит надсилається з допомогою інтерфейсу, пов'язаного з цієї підмережею. Якщо адреса таблиці не виявлено, то використовується інтерфейс підмережі, шлюз за замовчуванням.
  • Визначається MAC-адресу обраного мережевого інтерфейсу.
  • Відправляється ARP-запит (другий рівень стека):
ARP-запит:

Sender MAC: interface:mac:address:here

Sender IP: interface.ip.goes.here

Target MAC: FF:FF:FF:FF:FF:FF (Broadcast)

Target IP: target.ip.goes.here


У залежно від того, яке «залізо» розташоване між комп'ютером і роутером (маршрутизатором):

Пряме з'єднання:

  • Якщо комп'ютер безпосередньо підключений до роутера, то це пристрій посилає ARP-відповідь (ARP Reply).
Між ними концентратор (Хаб):

  • Якщо комп'ютер підключений до мережного концентратора, то цей хаб відправляє широкомовний ARP-запит з всіх своїх портів. Якщо роутер підключений  ж «проводу», то відправить ARP-відповідь.
Між ними комутатор (світч):

  • Якщо комп'ютер з'єднаний з мережевим комутатором, то цей світч перевірить локальну CAM/MAC-таблицю, щоб дізнатися, який порт ній має потрібний MAC-адресу. Якщо потрібної адреси таблиці немає, то він заново відправить широкомовний ARP-запит по всіх портів.
  • Якщо в таблиці є потрібна запис, то світч відправить ARP-запит на порт з шуканим MAC-адресою.
  • Якщо роутер «на одній лінії» з світчем, то він відповість (ARP Reply).
ARP-відповідь:

Sender MAC: target:mac:address:here

Sender IP: target.ip.goes.here

Target MAC: interface:mac:address:here

Target IP: interface.ip.goes.here


Тепер у мережевої бібліотеки є IP-адресу або DNS-сервера або шлюзу за замовчуванням, який можна використовувати для розв'язання доменного імені:

  • Порт 53 відкривається для відправки UDP-запиту до DNS-сервера (якщо розмір відповіді занадто великий, буде використаний TCP).
  • Якщо локальний або на стороні провайдера DNS-сервер «не знає» потрібну адресу, то запитується рекурсивний пошук, який проходить по списком вищестоящих DNS-серверів, поки не буде знайдена SOA-запису, а потім повертається результат.
5. Відкриття сокета
Коли браузер отримує IP-адресу кінцевого сервера, то він бере цю інформацію і дані про використовується порте з URL (80 порт для HTTP, 443 для HTTPS) і здійснює виклик функції
socket
системної бібліотеки і запитує потік TCP сокета  
AF_INET
та
SOCK_STREAM
.

  • Цей запит спочатку проходить через транспортний рівень, де збирається TCP-сегмент. У заголовок додається порт призначення, вихідний порт вибирається з динамічного пулу ядра (
    ip_local_port_range
    в Linux).
  • Одержаний сегмент відправляється на мережевий рівень, на якому додається додатковий IP-заголовок. Також включаються IP-адресу сервера призначення і адреса поточної машини — після цього пакет сформований.
  • Пакет передається на канальний рівень. Додається заголовок кадру, що включає MAC-адресу мережевої карти (NIC) комп'ютера, а також MAC-адреса шлюзу (локального роутера). Як і на попередніх етапах, якщо ядру нічого не відомо про MAC-адресу шлюзу, то для його знаходження відправляється широкомовний ARP-запит.
На цій точці пакет готовий до передачі через:

У випадку інтернет-з'єднання більшості приватних користувачів і невеликих компаній пакет буде відправлений з комп'ютера через локальну мережу, а потім через модем (
MOdulator/DEModulator
), який транслює цифрові одиниці і нулі в аналоговий сигнал, придатний для передачі по телефонної лінії, кабелю або бездротовим телефонним з'єднанням. На іншій стороні з'єднання розташований інший модем, який перетворює аналоговий сигнал в цифрові дані і передає їх наступного мережного вузла, де відбувається подальший аналіз даних про відправника та одержувача.

У зрештою пакет добереться до маршрутизатора, керуючого локальної підмережею. Потім він продовжить подорожувати від одного роутера до іншому, поки не добереться до сервера призначення. Кожен маршрутизатор на шляху буде витягувати адресу призначення з IP-заголовка і надсилати пакет на наступний хоп. Значення поля TTL (time to live) IP-заголовку буде кожен раз зменшуватися після проходження кожного роутера. Якщо значення поля TTL досягне нуля, пакет буде відкинутий (це відбудеться також якщо у маршрутизатора не буде місця в поточної черги   наприклад, через перевантаження мережі).

У час TCP-з'єднання відбувається безліч подібних запитів і відповідей.

5.1 Життєвий цикл TCP-з'єднання

a. Клієнт вибирає номер початкової послідовності (ISN) і відправляє пакет серверу з встановленим бітом SYN для відкриття з'єднання.

b. Сервер отримує пакет з біт SYN і, якщо готовий до встановлення з'єднання, то:

  • Вибирає власний номер початкової послідовності;
  • Встановлює SYN-біт, щоб повідомити про виборі початкової послідовності;
  • Копіює ISN клієнта +1 у полі ACK і додає ACK-прапор для позначення підтвердження отримання першого пакету.
c. Клієнт підтверджує з'єднання шляхом відправки пакету:

  • Збільшує номер своєї початкової послідовності;
  • Збільшує номер підтвердження отримання;
  • Встановлює поле ACK.
d. Дані передаються наступним чином:

  • Коли одна сторона надсилає N байтів, то збільшує значення поля SEQ на це число.
  • Коли друга сторона підтверджує отримання цього пакету (або ланцюжка пакетів), вона відправляє пакет ACK, в якому значення поля ACK дорівнює останньої отриманої послідовності.
e. Закриття з'єднання:

  • Сторона, яка хоче закрити з'єднання, відправляє пакет FIN;
  • Інша сторона підтверджує FIN (з допомогою ACK) і відправляє власний FIN-пакет;
  • Ініціатор припинення з'єднання підтверджує отримання FIN відправкою власного ACK.
6. TLS handshake
  • Клієнтський комп'ютер відправляє повідомлення
    ClientHello
    сервера з своєю версією протоколу TLS, списком підтримуваних алгоритмів шифрування і методів компресії даних.
  • Сервер відповідає клієнту повідомленням
    ServerHello
    , що містить версію TLS, вибраний метод шифрування, обрані методи компресії і публічний сертифікат сервісу, підписаний центром сертифікації. Сертифікат містить публічний ключ, який буде використовуватися клієнтом для шифрування решти процедури «рукостискання» (
    handshake
    ), поки не буде узгоджений симетричний ключ.
  • Клієнт підтверджує сертифікат сервера з допомогою свого списку центрів сертифікації. Якщо сертифікат підписаний центром з списку, сервера можна довіряти, і клієнт генерує рядок псевдовипадкових байтів і шифрує її з допомогою публічного ключа сервера. Ці випадкові байти можуть бути використані для визначення симетричного ключа.
  • Сервер розшифровує випадкові байти з допомогою свого таємного ключа і використовує ці байти для генерації своєї копії симетричного майстер-ключа.
  • Клієнт відправляє серверу повідомлення
    Finished
    , шифруючи хеш передачі з допомогою симетричного ключа.
  • Сервер генерує власний хеш, а потім розшифровує отриманий від клієнта хеш, щоб перевірити, чи співпаде він з власним. Якщо збіг знайдено, сервер відправляє клієнту власний відповідь
    Finished
    , також зашифрований симетричним ключем.
  • Після цього TLS-сесія передає дані програми (HTTP), зашифровані з допомогою підтвердженого симетричного ключа.
7. Протокол HTTP
Якщо використовується браузер був створений Google, то замість відправки HTTP-запиту для отримання сторінки, він відправить запит, щоб спробувати «домовитися» з сервером «апгрейд» протоколу з HTTP до SPDY («спіді»).

Якщо клієнт використовує HTTP-протокол і не підтримує SPDY, то відправляє серверу запит наступної форми:

GET / HTTP/1.1

Host: google.com

Connection: close

[інші заголовки]


де
[інші заголовки]
— це серія пар «ключ-значення», розбитих переносом рядка. (Тут передбачається, що в використаному браузері немає ніяких помилок, що порушують специфікацію HTTP. Також передбачається, що браузер використовує
HTTP/1.1
, інакше він не включати заголовок
Host
в запит і версія, віддана в відповідь на GET-запит може бути
HTTP/1.0
або
HTTP/0.9
).

HTTP/1.1
визначає опцію закриття з'єднання («close») для відправника    допомогою відбувається повідомлення про закриття з'єднання після завершення відповіді. До наприклад:

Connection: close
Програми
HTTP/1.1
, які не підтримують постійні з'єднання, зобов'язані включати опцію «close» в кожне повідомлення.

Після надсилання запиту і заголовків, браузер відправляє серверу одиничну порожню рядок, сигналізуючи про те, що вміст повідомлення закінчилося.

Сервер відповідає спеціальним кодом, який позначає статус запиту і включає відповідь наступної форми:

200 OK

[заголовки відповіді]


Після цього надсилається порожній рядок, а потім залишився вміст HTML-сторінок www.google.com. Сервер може потім закрити з'єднання, або, якщо того вимагають відправлені клієнтом заголовки, зберігати з'єднання відкритим для його використання наступними запитами.

Якщо HTTP-заголовки надіслані веб-браузером включають інформацію, якої сервера достатньо для визначення версії файлу, закэшированного в браузері і цей файл не змінювався з часу останнього запиту, то відповідь може прийняти наступну форму:

304 Not Modified

[заголовки відповіді]


і, відповідно, клієнту не надсилається ніякого контенту, замість цього браузер «дістає» HTML кеша.

Після розбору HTML браузер (і сервер) повторює процес завантаження для кожного ресурсу (зображення, стилі, скрипти, favicon.ico і так далі), який посилається HTML-сторінка, але при цьому змінюється адреса кожного запиту c
GET / HTTP/1.1
на
GET /$(відносний URL ресурсу www.google.com) HTTP/1.1
.

Якщо HTML посилається на ресурс, розміщений на домені, відмінному от google.com, то браузер повертається до крокам, що включає дозвіл доменного імені, а потім заново проходить процес до поточного стану, але вже для іншого домену. Заголовок
Host
в запиті замість google.com буде встановлений на потрібне доменне ім'я.

7.1 Обробка HTTP-запитів на сервері

HTTPD
(HTTP Daemon) є одним з інструментів обробки запитів/відповідей на стороні сервера. Найбільш популярні HTTPD-це сервери Apache або Nginx для Linux і IIS для Windows.

  HTTPD (HTTP Daemon) отримує запит.

  Сервер обробляє запит наступними параметрами:

  • Метод HTTP-запиту (
    GET
    ,
    POST
    ,
    HEAD
    ,
    PUT
    або
    DELETE
    ). У у разі URL-адреси, який користувач надрукував у рядку браузера, ми маємо справу з GET-запиту.
  • Домен. У нашому випадку   google.com.
  • Запитувані шляху/сторінки, в нашому випадку  
    /
    (немає запитаних шляхів,
    /
    — це шлях замовчуванням).
  Сервер перевіряє існування віртуального хоста, який відповідає google.com.

  Сервер перевіряє, що google.com може приймати GET-запити.

  Сервер перевіряє, чи має клієнт право використовувати цей метод (на IP-адреси, аутентифікації і інше).

  Якщо на сервері встановлений модуль перезапису (
mod_rewrite
для Apache або
URL Rewrite
для IIS), то він порівнює запит з одним з сконфігурованих правил. Якщо знаходиться збігається правило, сервер використовує його, щоб переписати запит.

  Сервер знаходить контент, який відповідає запиту, в нашому випадку він вивчить індексний файл.

  Далі сервер розбирає («парсити») файл з допомогою обробника. Якщо Google працює на PHP, то сервер використовує PHP для інтерпретації індексного файлу і направляє результат клієнтові.

8. За лаштунками браузера
Завдання браузера полягає в тому, щоб показувати користувачеві вибрані їм веб-ресурси, запитуючи їх з сервера і відображаючи в вікні перегляду. Як правило такими ресурсами є HTML-документи, але це може бути і PDF, зображення або контент іншого типу. Розташування ресурсів визначається з URL.

Спосіб, який браузер використовує для інтерпретації і відображення HTML-файлів описаний в специфікації HTML і CSS. Ці документи розроблені і підтримуються консорціумом W3C (World Wide Wib Consortium), яка займається стандартизацією веба.

Інтерфейси браузерів сильно схожі між собою. У них є велика кількість однакових елементів:

  • Адресна рядок, куди вставляються URL-адреси;
  • Кнопки повернення на попередню і наступну сторінку;
  • Можливість створення закладок;
  • Кнопки оновлення сторінки (рефреш) і зупинки завантаження поточних документів;
  • Кнопка «додому», яка повертає користувача на домашню сторінку.

Високорівнева структура браузера

Браузер включає наступні компоненти:

  • Користувальницький інтерфейс: нього входить адресна рядок, кнопки просування вперед/назад, меню закладок і так далі. Сюди відносяться всі елементи, крім вікна, в якому власне відображається веб-сторінка.
  • «Движок» браузера: Розподіляє дії між движок рендеринга і інтерфейсом користувача.
  • «Движок» рендеринга: Відповідає за відображення запитуваної контенту. До наприклад, якщо запитується HTML, то «движок» розбирає код HTML і CSS, а потім відображає отриманий контент на екрані.
  • Мережева частина: допомогою мережевих функцій браузер обробляє виклики, на зразок HTTP-запитів, з застосуванням різних реалізацій для різних платформ.
  • Бекенд користувача (UI): Використовується для відображення базових віджетів, начебто комбо-боксів і вікон.
  • Інтерпретатор JavaScript: Використовується для парсингу і виконання JavaScript-коду.
  • Сховище даних: Браузеру може знадобитися локально зберігати деякі дані (наприклад, cookie). Крім того, браузери підтримують різні механізми зберігання, такі як
    localStorage
    ,
    IndexedDB
    ,
    WebSQL
    та
    FileSystem
    .
9. Парсинг HTML
Движок рендеринга починає отримувати вміст запитуваного документа від мережного механізму браузера. Як правило, вміст надходить шматками по 8Кб. Головним завданням HTML-парсера є розбір розмітки в спеціальне дерево.

Получающееся на вихід дерево («parse tree») — це дерево DOM-елементів та вузлів атрибутів. DOM   скорочення від
Document Object Model
. Це модель об'єктного представлення HTML-документа і інтерфейс для взаємодії елементів HTML «зовнішнім світом» (наприклад, JavaScript-кодом). Коренем дерева є об'єкт «Документ».

Алгоритм розбору

HTML-не можна «розпарсити» з допомогою звичайних аналізаторів (низхідних або висхідних). Тому є кілька причин:

  • Вибачаюча майже що завгодно природа мови;
  • Той факт, що браузери володіють певною толерантністю до про помилки та підтримують популярні помилки в HTML.
  • Процес парсинга може заходити в глухий кут. У інших мовах код, який потрібно розібрати, не змінюється процесі аналізу, в  в HTML за допомогою динамічного коду (наприклад, скриптові елементи, що містять виклики
    document.write()
    ) можуть додаватися додаткові токени, в внаслідок чого сам процес парсинга модифікує висновок.
Неможливість використання звичних технологій парсинга призводить до того, що розробники браузерів реалізують власні механізми розбору HTML. Алгоритм парсинга докладно описаний у специфікації HTML5.

Алгоритм складається з двох етапів: токенизации і створення дерева.

Дії після завершення парсинга

Після цього браузер починає завантажувати зовнішні ресурси, пов'язані зі сторінкою (стилі, зображення, скрипти і так далі).

На цьому етапі браузер позначає документ, як інтерактивний і починає розбирати скрипти, які знаходяться в «відкладений» стані: є з них, що повинні бути виконані після парсингу. Після цього статус документа встановлюється в стан «
complete
» і ініціюється подія завантаження («
load
»).

Важливий момент: помилки
«Invalid Syntax»
при розборі не може бути, оскільки браузери виправляють будь «невалидный» контент і продовжують роботу.

10. Інтерпретація CSS
  •  час розбору браузер парсити CSS-файли, вміст тегів
    <style>
    та атрибутів «style» c  «лексичної і синтаксичної граматики CSS».
  • Кожен CSS-файл розбирається в об'єкт
    StyleSheet
    , кожен з таких об'єктів містить правила CSS з селекторами і об'єктами в згідно із граматикою CSS.
  • Парсер CSS може бути висхідним, так і низхідним.
11. Рендеринг сторінок
  • Шляхом перебору DOM-вузлів і обчислення для кожного вузла значень CSS-стилів створюється «Дерево розфарбовування» (Render Tree або Frame Tree).
  • Обчислюється бажана ширина кожного вузла нижній частині дерева — для цього підсумовуються значення бажаної ширини дочірніх вузлів, а також горизонтальні поля, межі і відступи вузлів.
  • Обчислюється реальна ширина кожного вузла зверху-вниз (доступна ширина кожного вузла виділяється його нащадкам).
  • Обчислюється висота кожного вузла знизу-вгору — для цього застосовується перенесення тексту і сумуються значення полів, висоти, відступів і меж нащадків.
  • Обчислюються координати кожного вузла (з використанням раніше отриманої інформації).
  • Якщо елементи плаваючі або спозиционированы абсолютно або відносно, вживаються більш складні дії. Більш докладно вони описані тут тут.
  • Створюються шари для опису того, які частини сторінки можна анімувати без необхідності повторного растеризації. Кожен об'єкт (кадру або фонового) присвоюється шару.
  • Для кожного шару на сторінці виділяються текстури.
  • Об'єкти (рендери/фрейми) кожного шару перебираються і для відповідних шарів виконуються команди відтворення. Растрування може здійснюватися процесором або можлива побудова на графічний процесор (GPU) через D2D/SkiaGL.
  • Всі перераховані вище кроки можуть вимагати повторного використання значення, збережені з останнього рендеринга сторінок, така инкрементальная робота вимагає менше витрат.
  • Шари сторінки відправляються процесу-компоновщику, де вони комбінуються з шарами для іншого видимого контенту (інтерфейс браузера, iframe-елементи, addon-панелі).
  • Обчислюються фінальні позиції шарів і через Direct3D/OpenGL віддаються композитні команди. Командні буфери GPU звільняються для асинхронного рендеринга і фрейм відправляється для відображення на екран.
12. Рендеринг GPU
  •  час процесу візуалізації рівні графічних обчислень можуть використовувати процесор комп'ютера або графічний процесор (GPU).
  •  другому випадку рівні графічного програмного забезпечення ділять завдання на безліч частин, що дозволяє використовувати паралелізм GPU для обчислення плаваючою точки, яка потрібна для процесу візуалізації.
13. Викликане користувачем і пост-рендеринговое виконання
Після завершення рендеринга, браузер виконує JavaScript-код в внаслідок спрацювання якогось часового механізму (так працюють дадлі на сторінці Google) або в результаті дій користувача (введення пошукового запиту у рядок і отримання рекомендацій відповідь). Також можуть спрацьовувати плагіни начебто Flash або Java (але не в розглянутому прикладі з домашньою сторінкою Google). Скрипти можуть зажадати обробки додаткових мережних запитів, змінювати сторінку або її шаблон, що призведе до наступного етапу рендеринга і відтворення.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.