Ladybird/Qt: Stop using history to drive navigation

Before this change we had to keep session history on browser side to
calculate a url for back/forward/reload action.
Now, with a mature enough implementation of navigation algorithms from
the specification, there is no need to use
history on the browser side to calculate navigation URLs because:
- Traversable navigable owns session history that is aware of all
  navigations, including those initiated by History API and Navigation
  API
- TraversableNavigable::traverse_the_history_by_delta() uses
  traversable's history to calculate the next URL based on delta, so
  there is no need for UI to keep sesion history.

In the future, we will likely want to add a way to pull session history
from WebContent to make it browsable from the UI.
This commit is contained in:
Aliaksandr Kalenik 2024-04-14 00:05:47 +02:00 committed by Alexander Kalenik
parent c96fc902ff
commit 882904b4bf
Notes: sideshowbarker 2024-07-17 02:38:39 +09:00
4 changed files with 34 additions and 63 deletions

View file

@ -267,14 +267,6 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, WebView::Cook
debug_request("dump-all-resolved-styles");
});
auto* dump_history_action = new QAction("Dump &History", this);
dump_history_action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_H));
dump_history_action->setIcon(load_icon_from_uri("resource://icons/16x16/history.png"sv));
debug_menu->addAction(dump_history_action);
QObject::connect(dump_history_action, &QAction::triggered, this, [this] {
debug_request("dump-history");
});
auto* dump_cookies_action = new QAction("Dump C&ookies", this);
dump_cookies_action->setIcon(load_icon_from_uri("resource://icons/browser/cookie.png"sv));
debug_menu->addAction(dump_cookies_action);
@ -441,7 +433,7 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, WebView::Cook
m_reload_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::Refresh));
m_go_back_action->setEnabled(false);
m_go_forward_action->setEnabled(false);
m_reload_action->setEnabled(false);
m_reload_action->setEnabled(true);
for (int i = 0; i <= 7; ++i) {
new QShortcut(QKeySequence(Qt::CTRL | static_cast<Qt::Key>(Qt::Key_1 + i)), this, [this, i] {
@ -470,8 +462,10 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, WebView::Cook
void BrowserWindow::set_current_tab(Tab* tab)
{
m_current_tab = tab;
if (tab)
if (tab) {
update_displayed_zoom_level();
tab->update_navigation_buttons_state();
}
}
void BrowserWindow::debug_request(ByteString const& request, ByteString const& argument)
@ -541,6 +535,7 @@ void BrowserWindow::initialize_tab(Tab* tab)
QObject::connect(tab, &Tab::title_changed, this, &BrowserWindow::tab_title_changed);
QObject::connect(tab, &Tab::favicon_changed, this, &BrowserWindow::tab_favicon_changed);
QObject::connect(tab, &Tab::audio_play_state_changed, this, &BrowserWindow::tab_audio_play_state_changed);
QObject::connect(tab, &Tab::navigation_buttons_state_changed, this, &BrowserWindow::tab_navigation_buttons_state_changed);
QObject::connect(&tab->view(), &WebContentView::urls_dropped, this, [this](auto& urls) {
VERIFY(urls.size());
@ -707,6 +702,12 @@ void BrowserWindow::tab_audio_play_state_changed(int index, Web::HTML::AudioPlay
}
}
void BrowserWindow::tab_navigation_buttons_state_changed(int index)
{
auto* tab = verify_cast<Tab>(m_tabs_container->widget(index));
tab->update_navigation_buttons_state();
}
QIcon BrowserWindow::icon_for_page_mute_state(Tab& tab) const
{
switch (tab.view().page_mute_state()) {

View file

@ -86,6 +86,7 @@ public slots:
void tab_title_changed(int index, QString const&);
void tab_favicon_changed(int index, QIcon const& icon);
void tab_audio_play_state_changed(int index, Web::HTML::AudioPlayState);
void tab_navigation_buttons_state_changed(int index);
Tab& new_tab_from_url(URL::URL const&, Web::HTML::ActivateTab);
Tab& new_tab_from_content(StringView html, Web::HTML::ActivateTab);
Tab& new_child_tab(Web::HTML::ActivateTab, Tab& parent, Web::HTML::WebViewHints, Optional<u64> page_index);

View file

@ -115,12 +115,9 @@ Tab::Tab(BrowserWindow* window, WebContentOptions const& web_content_options, St
m_hover_label->hide();
};
view().on_load_start = [this](const URL::URL& url, bool is_redirect) {
// If we are loading due to a redirect, we replace the current history entry
// with the loaded URL
if (is_redirect) {
m_history.replace_current(url, m_title.toUtf8().data());
}
view().on_load_start = [this](const URL::URL& url, bool) {
if (m_inspector_widget)
m_inspector_widget->reset();
auto url_serialized = qstring_from_ak_string(url.serialize());
@ -132,17 +129,6 @@ Tab::Tab(BrowserWindow* window, WebContentOptions const& web_content_options, St
m_location_edit->setText(url_serialized);
m_location_edit->setCursorPosition(0);
// Don't add to history if back or forward is pressed
if (!m_is_history_navigation) {
m_history.push(url, m_title.toUtf8().data());
}
m_is_history_navigation = false;
update_navigation_button_states();
if (m_inspector_widget)
m_inspector_widget->reset();
};
view().on_load_finish = [this](auto&) {
@ -150,25 +136,14 @@ Tab::Tab(BrowserWindow* window, WebContentOptions const& web_content_options, St
m_inspector_widget->inspect();
};
view().on_history_api_push_or_replace = [this](auto const& url, auto history_behavior) {
switch (history_behavior) {
case Web::HTML::HistoryHandlingBehavior::Push:
m_history.push(url, m_title.toUtf8().data());
break;
case Web::HTML::HistoryHandlingBehavior::Replace:
m_history.replace_current(url, m_title.toUtf8().data());
break;
}
view().on_url_change = [this](auto const& url) {
m_location_edit->setText(qstring_from_ak_string(url.serialize()));
update_navigation_button_states();
};
QObject::connect(m_location_edit, &QLineEdit::returnPressed, this, &Tab::location_edit_return_pressed);
view().on_title_change = [this](auto const& title) {
m_title = qstring_from_ak_string(title);
m_history.update_title(title);
emit title_changed(tab_index(), m_title);
};
@ -425,6 +400,12 @@ Tab::Tab(BrowserWindow* window, WebContentOptions const& web_content_options, St
emit audio_play_state_changed(tab_index(), play_state);
};
view().on_navigation_buttons_state_changed = [this](auto back_enabled, auto forward_enabled) {
m_can_navigate_back = back_enabled;
m_can_navigate_forward = forward_enabled;
emit navigation_buttons_state_changed(tab_index());
};
auto* search_selected_text_action = new QAction("&Search for <query>", this);
search_selected_text_action->setIcon(load_icon_from_uri("resource://icons/16x16/find.png"sv));
QObject::connect(search_selected_text_action, &QAction::triggered, this, [this]() {
@ -766,22 +747,12 @@ void Tab::load_html(StringView html)
void Tab::back()
{
if (!m_history.can_go_back())
return;
m_is_history_navigation = true;
m_history.go_back();
view().load(m_history.current().url.to_byte_string());
view().traverse_the_history_by_delta(-1);
}
void Tab::forward()
{
if (!m_history.can_go_forward())
return;
m_is_history_navigation = true;
m_history.go_forward();
view().load(m_history.current().url.to_byte_string());
view().traverse_the_history_by_delta(1);
}
void Tab::reload()
@ -825,10 +796,7 @@ int Tab::tab_index()
void Tab::debug_request(ByteString const& request, ByteString const& argument)
{
if (request == "dump-history")
m_history.dump();
else
m_view->debug_request(request, argument);
m_view->debug_request(request, argument);
}
void Tab::resizeEvent(QResizeEvent* event)
@ -845,11 +813,10 @@ void Tab::update_hover_label()
m_hover_label->raise();
}
void Tab::update_navigation_button_states()
void Tab::update_navigation_buttons_state()
{
m_window->go_back_action().setEnabled(m_history.can_go_back());
m_window->go_forward_action().setEnabled(m_history.can_go_forward());
m_window->reload_action().setEnabled(!m_history.is_empty());
m_window->go_back_action().setEnabled(m_can_navigate_back);
m_window->go_forward_action().setEnabled(m_can_navigate_forward);
}
bool Tab::event(QEvent* event)

View file

@ -54,6 +54,8 @@ public:
QIcon const& favicon() const { return m_favicon; }
void update_navigation_buttons_state();
public slots:
void focus_location_editor();
void location_edit_return_pressed();
@ -63,6 +65,7 @@ signals:
void title_changed(int id, QString const&);
void favicon_changed(int id, QIcon const&);
void audio_play_state_changed(int id, Web::HTML::AudioPlayState);
void navigation_buttons_state_changed(int id);
private:
virtual void resizeEvent(QResizeEvent*) override;
@ -70,7 +73,6 @@ private:
void recreate_toolbar_icons();
void update_hover_label();
void update_navigation_button_states();
void open_link(URL::URL const&);
void open_link_in_new_tab(URL::URL const&);
@ -85,7 +87,6 @@ private:
LocationEdit* m_location_edit { nullptr };
WebContentView* m_view { nullptr };
BrowserWindow* m_window { nullptr };
WebView::History m_history;
QString m_title;
QLabel* m_hover_label { nullptr };
QIcon m_favicon;
@ -117,11 +118,12 @@ private:
int tab_index();
bool m_is_history_navigation { false };
Ladybird::InspectorWidget* m_inspector_widget { nullptr };
QPointer<QDialog> m_dialog;
bool m_can_navigate_back { false };
bool m_can_navigate_forward { false };
};
}