Разрабатываем свой браузер с нуля. Часть первая: HTML Бэкенд, теория программирования
Долгое время занимался обработкой и анализом данных. Имеет хороший опыт проектирования больших/сложных программных продуктов. Активно участвует в opensource-проектах. Создает собственный браузерный движок.
lex.borisov@gmail.com
Зал «Дели + Калькутта»
8 ноября, 18:00
Расскажу, как создать самый быстрый и полноценный HTML-парсер с DOM. А также о том, чем отличается настоящий HTML-парсер от остальных. Как парсить по 200MB+ HTML в секунду и на выходе иметь правильный DOM (HTML Interfaces, DOM Interfaces).
Разберу тонкие места в HTML-спецификации и расскажу, что мешает создать лучшее решение. Затрону тему namespace’ов в HTML, и как они влияют на построение HTML-дерева.
Расскажу, зачем создавать собственный браузер/браузерный движок и почему именно на Си.
WebView — создай свой браузер
Android позволяет создать собственное окно для просмотра веб-страниц или даже создать свой клон браузера при помощи элемента WebView. Сам элемент использует движок WebKit и имеет множество свойств и методов. Мы ограничимся базовым примером создания приложения, с помощью которого сможем просматривать страницы в интернете. В последних версиях используется движок от Chromium, но большой разницы в этом нет для простых задач.
Создадим новый проект MyBrowser и сразу заменим код в файле разметки res/layout/activity_main.xml:
Теперь откроем файл активности MainActivity.java и объявим компонент WebView, а также инициализируем его — включим поддержку JavaScript и укажем страницу для загрузки.
// Kotlin class MainActivity : AppCompatActivity() < private lateinit var webView: WebView override fun onCreate(savedInstanceState: Bundle?) < super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) webView = findViewById(R.id.webView) webView.webViewClient = MyWebViewClient() // включаем поддержку JavaScript webView.getSettings().setJavaScriptEnabled(true) // указываем страницу загрузки webView.loadUrl("http://developer.alexanderklimov.ru/android") >>
// Java private WebView webView; public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.webView); // включаем поддержку JavaScript webView.getSettings().setJavaScriptEnabled(true); // указываем страницу загрузки webView.loadUrl("http://developer.alexanderklimov.ru/android"); >
Так как приложение будет использовать интернет, необходимо установить разрешение на доступ к интернету в файле-манифесте.
Там же в манифесте модифицируем строчку для экрана, удалив заголовок из нашего приложения (выделено жирным):
Запустим приложение. В нашем распоряжении появился простейший вьювер веб-страниц, но с одним недостатком. Если вы щёлкнете на любой ссылке, то у вас автоматически запустится браузер по умолчанию и новая страница отобразится уже там. Точнее так было раньше. На новых устройствах при запуске приложения сразу открывается браузер.
Чтобы решить данную проблему и открывать ссылки в своей программе, нужно переопределить класс WebViewClient и позволить нашему приложению обрабатывать ссылки. Добавим в коде вложенный класс:
// Kotlin private class MyWebViewClient : WebViewClient() < @TargetApi(Build.VERSION_CODES.N) override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean < view.loadUrl(request.url.toString()) return true >// Для старых устройств override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean < view.loadUrl(url) return true >>
// Java private class MyWebViewClient extends WebViewClient < @TargetApi(Build.VERSION_CODES.N) @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) < view.loadUrl(request.getUrl().toString()); return true; >// Для старых устройств @Override public boolean shouldOverrideUrlLoading(WebView view, String url) < view.loadUrl(url); return true; >>
Затем в методе onCreate() определим экземпляр MyWebViewClient. Он может находиться в любом месте после инициализации объекта WebView:
// Kotlin webView.webViewClient = MyWebViewClient()
// Java webView.setWebViewClient(new MyWebViewClient());
Теперь в нашем приложении создан WebViewClient, который позволяет загружать любой указанный URL, выбранный в WebView, в сам контейнер WebView, а не запускать браузер. За данную функциональность отвечает метод shouldOverrideUrlLoading(WebView, String), в котором мы указываем текущий WebView и нужный URL. Возвращаемое значение true говорит о том, что мы не нуждаемся в запуске стороннего браузера, а самостоятельно загрузим контент по ссылке. В версии API 24 добавили перегруженную версию метода, учитывайте это обстоятельство.
Повторно запустите программу и убедитесь, что ссылки загружаются теперь в самом приложении. Но теперь возникла ещё одна проблема. Мы не можем вернуться к предыдущей странице. Если мы нажмём на кнопку «BACK» (Назад) на устройстве, то просто закроем своё приложение. Для решения новой проблемы нам необходимо обрабатывать нажатие кнопки «BACK». Добавляем новый метод:
// Kotlin override fun onBackPressed() < if (webView.canGoBack()) < webView.goBack() >else < super.onBackPressed() >>
// Java @Override public void onBackPressed() < if(webView.canGoBack()) < webView.goBack(); >else < super.onBackPressed(); >>
Мы должны проверить, что WebView поддерживает навигацию на предыдущую страницу. Если условие верно, тогда вызывается метод goBack(), который возвращает нас на предыдущую страницу на один шаг назад. Если таких страниц набралось несколько, то мы можем последовательно вернуться к самой первой странице. При этом метод всегда будет возвращать значение true. Когда мы вернёмся на самую первую страницу, с которой начали путешествие по интернету, то вернётся значение false и обработкой нажатия кнопки BACK займётся уже сама система, которая закроет экран приложения.
Запустите приложение ещё раз. У вас появился свой собственный веб-браузер, позволяющий ходить по ссылкам и возвращаться на предыдущую страницу. Изучив документацию, вы можете оснастить приложение и другим вкусными плюшками для своего браузера.

Если вам нужно часть ссылок, ведущих на ваш сайт открывать в браузере, а локальные ссылки открывать в приложении, то применяйте условие с разными возвращаемыми значениями.
public class MyWebViewClient extends WebViewClient < @Override public boolean shouldOverrideUrlLoading(WebView view, String url) < if(Uri.parse(url).getHost().endsWith("developer.alexanderklimov.ru")) < return false; >Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); view.getContext().startActivity(intent); return true; > >
Универсальный метод, который все локальные ссылки откроет в приложении, остальные в браузере (меняем одну строчку):
public class MyAppWebViewClient extends WebViewClient < @Override public boolean shouldOverrideUrlLoading(WebView view, String url) < if(Uri.parse(url).getHost().length() == 0) < return false; >Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); view.getContext().startActivity(intent); return true; > >
А сейчас немного усложним пример, чтобы у пользователя появилась альтернатива стандартным браузерам.
Чтобы было понятнее, переделаем пример следующим образом. Создайте две активности. На первой активности разместите кнопку для перехода на вторую активность, а на второй активности разместите компонент WebView.
В манифесте прописываем у второй активности фильтр.
Код для кнопки для перехода на вторую активность.
public void onClick(View view) < Intent intent = new Intent("ru.alexanderklimov.Browser"); intent.setData(Uri.parse("http://developer.alexanderklimov.ru/android/")); startActivity(intent); >
Мы создали собственное намерение с указанием фильтра и предоставили данные — адрес сайта.
Вторая активность должна принять данные:
package ru.alexanderklimov.testapplication; import android.net.Uri; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.webkit.WebView; import android.webkit.WebViewClient; public class SecondActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); Uri url = getIntent().getData(); WebView webView = findViewById(R.id.webView); webView.setWebViewClient(new Callback()); webView.loadUrl(url.toString()); > private class Callback extends WebViewClient < @Override public boolean shouldOverrideUrlLoading (WebView view, String url) < return(false); >> >
В фильтре для второй активности мы указали два действия.
Это означает, что любые активности (читай, приложения) могут вызвать вашу активность с мини-браузером по такому же принципу. Запустите в студии в отдельном окне любой старый проект или создайте новый и добавьте в него кнопку и пропишите тот же код, который мы использовали для щелчка кнопки.
Запустите второе приложение (первое приложение можно закрыть) и нажмите на кнопку. У вас запустится не первое приложение с начальным экраном, а сразу вторая активность с мини-браузером. Таким образом, любое приложение может запустить браузер, не зная имени класса вашей активности, а используя только строку «ru.alexanderklimov.Browser», передаваемую в Intent. При этом ваша активность с браузером должна иметь категорию по умолчанию и данные. Напомню:
Вы можете представить свою строку в виде строковой константы и сообщить всем потенциальным пользователям вашего браузера, как они могут запустить его у себя. Но в Android уже есть такая готовая константа ACTION_VIEW, которая по справке документации представляет собой следующее:
public static final java.lang.String ACTION_VIEW = "android.intent.action.VIEW";
Перепишем код для кнопки у второго приложения
Intent(android.content.Intent.ACTION_VIEW, Uri.parse("http://developer.alexanderklimov.ru/android/")); startActivity(intent);
Что произойдёт на этот раз? Мы помним, что у нас прописано два действия, включая и android.intent.action.VIEW. А значит наше первое приложение с браузером тоже должно распознавать эту команду, когда какое-то приложение у пользователя использует этот код. На эмуляторе как минимум есть одна такая программа «Browser», и теперь к ней добавилась наша вторая активность из первого приложения. На экране появится выбор из двух приложений.

А если удалить все альтернативные браузеры и оставить только вашу программу, то и выбора не будет. Ваш браузер станет основным. И если какое-то приложение захочет запустить веб-страницу указанным способом, то откроется ваша программа.
Небольшое замечание. Если заменить последнюю строчку на такую:
startActivity(Intent.createChooser(intent, "Мяу. "));
То в окне выбора программы вместо верхней строки «Open with» или её локального перевода появится ваша строка. Но не это главное. Если по каким-то причинам на устройстве не окажется ни одного браузера, то данный вариант кода не вызовет краха приложения, в отличие от первоначального варианта. Поэтому используйте предложенный вариант ради надёжности.
Относительно недавно увидел новый способ открытия ссылок вне браузера. Необходимо использовать флаг FLAG_ACTIVITY_REQUIRE_NON_BROWSER.
val url = "http://developer.alexanderklimov.ru" val intent = Intent(ACTION_VIEW, Uri.parse(url)).apply
Как создать свой собственный веб-браузер в Visual Studio Community
Чтобы создать сегодня свой сайт, совсем необязательно знать языки программирования, большинство веб-ресурсов не пишется, а собирается в различных программах-конструкторах, получивших в последнее время широкое распространение. Конструкторы эти становятся настолько совершенными, что создавать в них можно даже собственные десктопные приложения. Пример работы в одном из таких конструкторов мы сегодня рассмотрим, создав в нём с нуля свой браузер.
Естественно, браузер будет обладать минимальным набором функций, но ведь мы и не претендуем на звание профессиональных разработчиков. В качестве конструктора мы будем использовать Visual Studio Community 2019 — бесплатную интегрированную среду разработки для написания и запуска кода на разных платформах. Название может показаться пугающим, в действительности ничего такого архисложного нет, код писать почти не придется, вместо него мы будем собирать его готовые блоки, представленные графическими элементами.
Итак, идем на сайт visualstudio.microsoft.com/ru, скачиваем файл автономного установщика и запускаем.

Выбираем установку Visual Studio Community 2019.

В меню «Рабочие нагрузки» выбираем блок «Windows», а в нём — опцию «Разработка классических приложений .NET». Жмем «Установить».

Процедура займет определенное время, поскольку потребуется скачать более гигабайта данных.

По завершении установки и запуска платформы.

Выбираем в меню «Создание проекта».

Прокручиваем список шаблонов и находим в нём Приложение Windows Forms в (.NET Framework).

Жмем «Далее», даем будущему браузеру имя и нажимаем «Создать».

Через несколько секунд перед нами предстает пустая форма, в ней будем размещать элементы управления веб-обозревателем. Вызываем нажатием на узкую полоску слева панель инструментов, раскрываем пункт «Все формы Windows Form» и выбираем двойным кликом «WebBrowser».

Справа располагаются другие две панели, верхняя содержит список файлов проекта, нижняя — свойства пока еще пустого окна. Здесь можно изменять параметры выбранного элемента — устанавливать размеры окна, его прозрачность, фон, включать и отключать полосы прокрутки и так далее. Если это будет не окно, а другой элемент, скажем, кнопка, то и параметры будут другие.
Рабочее окно уже есть, теперь следует позаботиться об элементах управления. Создадим область для панели инструментов обозревателя. Кликаем по маленькой иконке-треугольнику около кнопки закрытия окна и жмем «Открепить в родительском контейнере».

А затем растягиваем появившуюся пунктирную линию в окне будущего браузера, формируя таким образом панель управления.


Теперь создадим кнопки «Вперед», «Назад» и «Домой», «Обновить», для чего возвращаемся на панель инструментов и перетаскиваем на форму элемент «Button» столько раз, сколько нужно создать кнопок.

Желающие также могут создать текстовое поле для ввода текстовых данных (TextBox) и кнопки перехода, но мы ограничимся четырьмя элементами. Разместив их на форме должным образом, кликаем по каждому из них и настраиваем их параметры — даем им соответствующие наименования, меняем, если нужно, цвет и так далее. Теперь настала пора самого главного — назначения управляющим элементам действий. Для этого дважды кликаем по каждой из кнопок и прописываем в месте, где установился курсор следующий код:
• Для кнопки «Обновить» — webBrowser1.Refresh();
• Для кнопки «Домой» — webBrowser1.Navigate(«www.google.com»);
• Для кнопки «Вперед» — webBrowser1.GoForward();
• Для кнопки «Назад» — webBrowser1.GoBack();

Сохраняем результат через меню «Файл» -> «Сохранить всё» и запускаем компиляцию приложения нажатием кнопки «Пуск» на панели управления средой разработки (исполняемый файл находится в папке проекта) .

Через несколько секунд собственноручно сконструированный браузер запустится.

Если элементы на форме окажутся не там, где предполагалось, исправляем, перемещая их в визуальном редакторе.
Конечно, это будет очень простой браузер без закладок, поддержки тем и расширений, да и корректность отображения сайтов в нём в не гарантируется, зато вы можете быть уверены в его «чистоте».


Размер созданного браузера у нас составил всего 9,5 килобайт, но этого вполне хватило, чтобы вместить в него базовый функционал, обеспечивающий не только веб-серфинг, но и скачивание файлов, а также просмотр мультимедийного контента в потоковом режиме.
Как создать свой браузер? [закрыт]
Закрыт. Данный вопрос необходимо конкретизировать. Ответы на него в данный момент не принимаются.
Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме.
Закрыт 8 лет назад .
Подскажите, как создать браузер, какие для этого использовать слова и команды?
- веб-программирование
- браузер
Отслеживать
51.2k 86 86 золотых знаков 266 266 серебряных знаков 505 505 бронзовых знаков
задан 16 мая 2011 в 16:07
13 1 1 золотой знак 1 1 серебряный знак 2 2 бронзовых знака
Повторю цитату: из буханки белого хлеба и проволоки можно сделать троллейбус но ЗАЧЕМ? Если хотите сделать браузер начните с изучения документаций HTML, XHTML и т.д. Напишите свой движок, движок IE любой школьник знакомый с Delphi или C# использовать умеет.
