1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:17:44 +00:00

Browser+LibWeb: Pave the way for using WebContentView in Browser

This commit sets everything up, but we still always instantiate a plain
Web::PageView in Browser::Tab..
This commit is contained in:
Andreas Kling 2020-07-06 21:46:37 +02:00
parent 49b9a0a665
commit d8be535579
6 changed files with 177 additions and 73 deletions

View file

@ -56,6 +56,7 @@
#include <LibWeb/Loader/ResourceLoader.h> #include <LibWeb/Loader/ResourceLoader.h>
#include <LibWeb/PageView.h> #include <LibWeb/PageView.h>
#include <LibWeb/Parser/CSSParser.h> #include <LibWeb/Parser/CSSParser.h>
#include <LibWeb/WebContentView.h>
namespace Browser { namespace Browser {
@ -73,20 +74,25 @@ URL url_from_user_input(const String& input)
return URL(builder.build()); return URL(builder.build());
} }
Tab::Tab() Tab::Tab(Type type)
: m_type(type)
{ {
auto& widget = *this; auto& widget = *this;
set_layout<GUI::VerticalBoxLayout>(); set_layout<GUI::VerticalBoxLayout>();
m_toolbar_container = widget.add<GUI::ToolBarContainer>(); m_toolbar_container = widget.add<GUI::ToolBarContainer>();
auto& toolbar = m_toolbar_container->add<GUI::ToolBar>(); auto& toolbar = m_toolbar_container->add<GUI::ToolBar>();
if (m_type == Type::InProcessWebView)
m_page_view = widget.add<Web::PageView>(); m_page_view = widget.add<Web::PageView>();
else
m_web_content_view = widget.add<WebContentView>();
m_go_back_action = GUI::CommonActions::make_go_back_action([this](auto&) { m_go_back_action = GUI::CommonActions::make_go_back_action([this](auto&) {
m_history.go_back(); m_history.go_back();
update_actions(); update_actions();
TemporaryChange<bool> change(m_should_push_loads_to_history, false); TemporaryChange<bool> change(m_should_push_loads_to_history, false);
m_page_view->load(m_history.current()); load(m_history.current());
}, },
this); this);
@ -94,7 +100,7 @@ Tab::Tab()
m_history.go_forward(); m_history.go_forward();
update_actions(); update_actions();
TemporaryChange<bool> change(m_should_push_loads_to_history, false); TemporaryChange<bool> change(m_should_push_loads_to_history, false);
m_page_view->load(m_history.current()); load(m_history.current());
}, },
this); this);
@ -102,13 +108,14 @@ Tab::Tab()
toolbar.add_action(*m_go_forward_action); toolbar.add_action(*m_go_forward_action);
toolbar.add_action(GUI::CommonActions::make_go_home_action([this](auto&) { toolbar.add_action(GUI::CommonActions::make_go_home_action([this](auto&) {
m_page_view->load(g_home_url); load(g_home_url);
}, },
this)); this));
m_reload_action = GUI::CommonActions::make_reload_action([this](auto&) { m_reload_action = GUI::CommonActions::make_reload_action(
[this](auto&) {
TemporaryChange<bool> change(m_should_push_loads_to_history, false); TemporaryChange<bool> change(m_should_push_loads_to_history, false);
m_page_view->reload(); reload();
}, },
this); this);
@ -120,8 +127,8 @@ Tab::Tab()
m_location_box->on_return_pressed = [this] { m_location_box->on_return_pressed = [this] {
auto url = url_from_user_input(m_location_box->text()); auto url = url_from_user_input(m_location_box->text());
m_page_view->load(url); load(url);
m_page_view->set_focus(true); view().set_focus(true);
}; };
m_location_box->add_custom_context_menu_action(GUI::Action::create("Paste & Go", [this](auto&) { m_location_box->add_custom_context_menu_action(GUI::Action::create("Paste & Go", [this](auto&) {
@ -136,7 +143,7 @@ Tab::Tab()
m_bookmark_button->set_preferred_size(22, 22); m_bookmark_button->set_preferred_size(22, 22);
m_bookmark_button->on_click = [this](auto) { m_bookmark_button->on_click = [this](auto) {
auto url = m_page_view->document()->url().to_string(); auto url = this->url().to_string();
if (BookmarksBarWidget::the().contains_bookmark(url)) { if (BookmarksBarWidget::the().contains_bookmark(url)) {
BookmarksBarWidget::the().remove_bookmark(url); BookmarksBarWidget::the().remove_bookmark(url);
} else { } else {
@ -145,7 +152,7 @@ Tab::Tab()
update_bookmark_button(url); update_bookmark_button(url);
}; };
m_page_view->on_load_start = [this](auto& url) { hooks().on_load_start = [this](auto& url) {
m_location_box->set_icon(nullptr); m_location_box->set_icon(nullptr);
m_location_box->set_text(url.to_string()); m_location_box->set_text(url.to_string());
if (m_should_push_loads_to_history) if (m_should_push_loads_to_history)
@ -154,20 +161,20 @@ Tab::Tab()
update_bookmark_button(url.to_string()); update_bookmark_button(url.to_string());
}; };
m_page_view->on_link_click = [this](auto& url, auto& target, unsigned modifiers) { hooks().on_link_click = [this](auto& url, auto& target, unsigned modifiers) {
if (target == "_blank" || modifiers == Mod_Ctrl) { if (target == "_blank" || modifiers == Mod_Ctrl) {
on_tab_open_request(url); on_tab_open_request(url);
} else { } else {
m_page_view->load(url); load(url);
} }
}; };
m_link_context_menu = GUI::Menu::construct(); m_link_context_menu = GUI::Menu::construct();
m_link_context_menu->add_action(GUI::Action::create("Open", [this](auto&) { m_link_context_menu->add_action(GUI::Action::create("Open", [this](auto&) {
m_page_view->on_link_click(m_link_context_menu_url, "", 0); hooks().on_link_click(m_link_context_menu_url, "", 0);
})); }));
m_link_context_menu->add_action(GUI::Action::create("Open in new tab", [this](auto&) { m_link_context_menu->add_action(GUI::Action::create("Open in new tab", [this](auto&) {
m_page_view->on_link_click(m_link_context_menu_url, "_blank", 0); hooks().on_link_click(m_link_context_menu_url, "_blank", 0);
})); }));
m_link_context_menu->add_action(GUI::Action::create("Copy link", [this](auto&) { m_link_context_menu->add_action(GUI::Action::create("Copy link", [this](auto&) {
GUI::Clipboard::the().set_data(m_link_context_menu_url.to_string()); GUI::Clipboard::the().set_data(m_link_context_menu_url.to_string());
@ -184,7 +191,7 @@ Tab::Tab()
(void)window.leak_ref(); (void)window.leak_ref();
})); }));
m_page_view->on_link_context_menu_request = [this](auto& url, auto& screen_position) { hooks().on_link_context_menu_request = [this](auto& url, auto& screen_position) {
m_link_context_menu_url = url; m_link_context_menu_url = url;
m_link_context_menu->popup(screen_position); m_link_context_menu->popup(screen_position);
}; };
@ -193,9 +200,9 @@ Tab::Tab()
hooks().on_link_click(href, "_blank", 0); hooks().on_link_click(href, "_blank", 0);
}; };
m_page_view->on_title_change = [this](auto& title) { hooks().on_title_change = [this](auto& title) {
if (title.is_null()) { if (title.is_null()) {
m_title = m_page_view->document()->url().to_string(); m_title = url().to_string();
} else { } else {
m_title = title; m_title = title;
} }
@ -203,19 +210,22 @@ Tab::Tab()
on_title_change(m_title); on_title_change(m_title);
}; };
m_page_view->on_favicon_change = [this](auto& icon) { hooks().on_favicon_change = [this](auto& icon) {
m_icon = icon; m_icon = icon;
m_location_box->set_icon(&icon); m_location_box->set_icon(&icon);
if (on_favicon_change) if (on_favicon_change)
on_favicon_change(icon); on_favicon_change(icon);
}; };
m_page_view->on_set_document = [this](auto* document) { // FIXME: Support JS console in multi-process mode.
if (m_type == Type::InProcessWebView) {
hooks().on_set_document = [this](auto* document) {
if (document && m_console_window) { if (document && m_console_window) {
auto* console_widget = static_cast<ConsoleWidget*>(m_console_window->main_widget()); auto* console_widget = static_cast<ConsoleWidget*>(m_console_window->main_widget());
console_widget->set_interpreter(document->interpreter().make_weak_ptr()); console_widget->set_interpreter(document->interpreter().make_weak_ptr());
} }
}; };
}
auto focus_location_box_action = GUI::Action::create( auto focus_location_box_action = GUI::Action::create(
"Focus location box", { Mod_Ctrl, Key_L }, [this](auto&) { "Focus location box", { Mod_Ctrl, Key_L }, [this](auto&) {
@ -226,15 +236,15 @@ Tab::Tab()
m_statusbar = widget.add<GUI::StatusBar>(); m_statusbar = widget.add<GUI::StatusBar>();
m_page_view->on_link_hover = [this](auto& url) { hooks().on_link_hover = [this](auto& url) {
if (url.is_valid()) if (url.is_valid())
m_statusbar->set_text(url.to_string()); m_statusbar->set_text(url.to_string());
else else
m_statusbar->set_text(""); m_statusbar->set_text("");
}; };
m_page_view->on_url_drop = [this](auto& url) { hooks().on_url_drop = [this](auto& url) {
m_page_view->load(url); load(url);
}; };
m_menubar = GUI::MenuBar::construct(); m_menubar = GUI::MenuBar::construct();
@ -268,6 +278,7 @@ Tab::Tab()
auto view_source_action = GUI::Action::create( auto view_source_action = GUI::Action::create(
"View source", { Mod_Ctrl, Key_U }, [this](auto&) { "View source", { Mod_Ctrl, Key_U }, [this](auto&) {
if (m_type == Type::InProcessWebView) {
ASSERT(m_page_view->document()); ASSERT(m_page_view->document());
auto url = m_page_view->document()->url().to_string(); auto url = m_page_view->document()->url().to_string();
auto source = m_page_view->document()->source(); auto source = m_page_view->document()->source();
@ -280,11 +291,15 @@ Tab::Tab()
window->set_title(url); window->set_title(url);
window->show(); window->show();
(void)window.leak_ref(); (void)window.leak_ref();
} else {
TODO();
}
}, },
this); this);
auto inspect_dom_tree_action = GUI::Action::create( auto inspect_dom_tree_action = GUI::Action::create(
"Inspect DOM tree", { Mod_None, Key_F12 }, [this](auto&) { "Inspect DOM tree", { Mod_None, Key_F12 }, [this](auto&) {
if (m_type == Type::InProcessWebView) {
if (!m_dom_inspector_window) { if (!m_dom_inspector_window) {
m_dom_inspector_window = GUI::Window::construct(); m_dom_inspector_window = GUI::Window::construct();
m_dom_inspector_window->set_rect(100, 100, 300, 500); m_dom_inspector_window->set_rect(100, 100, 300, 500);
@ -295,6 +310,9 @@ Tab::Tab()
inspector_widget->set_document(m_page_view->document()); inspector_widget->set_document(m_page_view->document());
m_dom_inspector_window->show(); m_dom_inspector_window->show();
m_dom_inspector_window->move_to_front(); m_dom_inspector_window->move_to_front();
} else {
TODO();
}
}, },
this); this);
@ -304,6 +322,7 @@ Tab::Tab()
inspect_menu.add_action(GUI::Action::create( inspect_menu.add_action(GUI::Action::create(
"Open JS Console", { Mod_Ctrl, Key_I }, [this](auto&) { "Open JS Console", { Mod_Ctrl, Key_I }, [this](auto&) {
if (m_type == Type::InProcessWebView) {
if (!m_console_window) { if (!m_console_window) {
m_console_window = GUI::Window::construct(); m_console_window = GUI::Window::construct();
m_console_window->set_rect(100, 100, 500, 300); m_console_window->set_rect(100, 100, 500, 300);
@ -314,32 +333,51 @@ Tab::Tab()
console_widget->set_interpreter(m_page_view->document()->interpreter().make_weak_ptr()); console_widget->set_interpreter(m_page_view->document()->interpreter().make_weak_ptr());
m_console_window->show(); m_console_window->show();
m_console_window->move_to_front(); m_console_window->move_to_front();
} else {
TODO();
}
}, },
this)); this));
auto& debug_menu = m_menubar->add_menu("Debug"); auto& debug_menu = m_menubar->add_menu("Debug");
debug_menu.add_action(GUI::Action::create( debug_menu.add_action(GUI::Action::create(
"Dump DOM tree", [this](auto&) { "Dump DOM tree", [this](auto&) {
if (m_type == Type::InProcessWebView) {
Web::dump_tree(*m_page_view->document()); Web::dump_tree(*m_page_view->document());
} else {
TODO();
}
}, },
this)); this));
debug_menu.add_action(GUI::Action::create( debug_menu.add_action(GUI::Action::create(
"Dump Layout tree", [this](auto&) { "Dump Layout tree", [this](auto&) {
if (m_type == Type::InProcessWebView) {
Web::dump_tree(*m_page_view->document()->layout_node()); Web::dump_tree(*m_page_view->document()->layout_node());
} else {
TODO();
}
}, },
this)); this));
debug_menu.add_action(GUI::Action::create( debug_menu.add_action(GUI::Action::create(
"Dump Style sheets", [this](auto&) { "Dump Style sheets", [this](auto&) {
if (m_type == Type::InProcessWebView) {
for (auto& sheet : m_page_view->document()->style_sheets().sheets()) { for (auto& sheet : m_page_view->document()->style_sheets().sheets()) {
dump_sheet(sheet); dump_sheet(sheet);
} }
} else {
TODO();
}
}, },
this)); this));
debug_menu.add_separator(); debug_menu.add_separator();
auto line_box_borders_action = GUI::Action::create_checkable( auto line_box_borders_action = GUI::Action::create_checkable(
"Line box borders", [this](auto& action) { "Line box borders", [this](auto& action) {
if (m_type == Type::InProcessWebView) {
m_page_view->set_should_show_line_box_borders(action.is_checked()); m_page_view->set_should_show_line_box_borders(action.is_checked());
m_page_view->update(); m_page_view->update();
} else {
TODO();
}
}, },
this); this);
line_box_borders_action->set_checked(false); line_box_borders_action->set_checked(false);
@ -366,7 +404,7 @@ Tab::Tab()
m_page_context_menu->add_separator(); m_page_context_menu->add_separator();
m_page_context_menu->add_action(*view_source_action); m_page_context_menu->add_action(*view_source_action);
m_page_context_menu->add_action(*inspect_dom_tree_action); m_page_context_menu->add_action(*inspect_dom_tree_action);
m_page_view->on_context_menu_request = [&](auto& screen_position) { hooks().on_context_menu_request = [&](auto& screen_position) {
m_page_context_menu->popup(screen_position); m_page_context_menu->popup(screen_position);
}; };
} }
@ -377,7 +415,22 @@ Tab::~Tab()
void Tab::load(const URL& url) void Tab::load(const URL& url)
{ {
if (m_type == Type::InProcessWebView)
m_page_view->load(url); m_page_view->load(url);
else
m_web_content_view->load(url);
}
URL Tab::url() const
{
if (m_type == Type::InProcessWebView)
return m_page_view->url();
return m_web_content_view->url();
}
void Tab::reload()
{
load(url());
} }
void Tab::update_actions() void Tab::update_actions()
@ -411,7 +464,7 @@ void Tab::did_become_active()
if (modifiers & Mod_Ctrl) if (modifiers & Mod_Ctrl)
on_tab_open_request(url); on_tab_open_request(url);
else else
m_page_view->load(url); load(url);
}; };
BookmarksBarWidget::the().on_bookmark_hover = [this](auto&, auto& url) { BookmarksBarWidget::the().on_bookmark_hover = [this](auto&, auto& url) {
@ -433,4 +486,16 @@ void Tab::context_menu_requested(const Gfx::IntPoint& screen_position)
m_tab_context_menu->popup(screen_position); m_tab_context_menu->popup(screen_position);
} }
GUI::Widget& Tab::view()
{
if (m_type == Type::InProcessWebView)
return *m_page_view;
return *m_web_content_view;
}
Web::WebViewHooks& Tab::hooks()
{
if (m_type == Type::InProcessWebView)
return *m_page_view;
return *m_web_content_view;}
} }

View file

@ -32,15 +32,29 @@
#include <LibHTTP/HttpJob.h> #include <LibHTTP/HttpJob.h>
#include <LibWeb/Forward.h> #include <LibWeb/Forward.h>
class WebContentView;
namespace Web {
class WebViewHooks;
}
namespace Browser { namespace Browser {
class Tab final : public GUI::Widget { class Tab final : public GUI::Widget {
C_OBJECT(Tab); C_OBJECT(Tab);
public: public:
enum class Type {
InProcessWebView,
OutOfProcessWebView,
};
virtual ~Tab() override; virtual ~Tab() override;
URL url() const;
void load(const URL&); void load(const URL&);
void reload();
void did_become_active(); void did_become_active();
void context_menu_requested(const Gfx::IntPoint& screen_position); void context_menu_requested(const Gfx::IntPoint& screen_position);
@ -53,14 +67,22 @@ public:
const String& title() const { return m_title; } const String& title() const { return m_title; }
const Gfx::Bitmap* icon() const { return m_icon; } const Gfx::Bitmap* icon() const { return m_icon; }
private: GUI::Widget& view();
Tab();
private:
explicit Tab(Type);
Web::WebViewHooks& hooks();
void update_actions(); void update_actions();
void update_bookmark_button(const String& url); void update_bookmark_button(const String& url);
Type m_type;
History<URL> m_history; History<URL> m_history;
RefPtr<Web::PageView> m_page_view; RefPtr<Web::PageView> m_page_view;
RefPtr<WebContentView> m_web_content_view;
RefPtr<GUI::Action> m_go_back_action; RefPtr<GUI::Action> m_go_back_action;
RefPtr<GUI::Action> m_go_forward_action; RefPtr<GUI::Action> m_go_forward_action;
RefPtr<GUI::Action> m_reload_action; RefPtr<GUI::Action> m_reload_action;

View file

@ -105,6 +105,11 @@ int main(int argc, char** argv)
return 1; return 1;
} }
if (unveil("/tmp/portal/webcontent", "rw") < 0) {
perror("unveil");
return 1;
}
unveil(nullptr, nullptr); unveil(nullptr, nullptr);
auto m_config = Core::ConfigFile::get_for_app("Browser"); auto m_config = Core::ConfigFile::get_for_app("Browser");
@ -151,7 +156,8 @@ int main(int argc, char** argv)
Function<void(URL url, bool activate)> create_new_tab; Function<void(URL url, bool activate)> create_new_tab;
create_new_tab = [&](auto url, auto activate) { create_new_tab = [&](auto url, auto activate) {
auto& new_tab = tab_widget.add_tab<Browser::Tab>("New tab"); auto type = Browser::Tab::Type::InProcessWebView;
auto& new_tab = tab_widget.add_tab<Browser::Tab>("New tab", type);
tab_widget.set_bar_visible(!window->is_fullscreen() && tab_widget.children().size() > 1); tab_widget.set_bar_visible(!window->is_fullscreen() && tab_widget.children().size() > 1);
tab_widget.set_tab_icon(new_tab, default_favicon); tab_widget.set_tab_icon(new_tab, default_favicon);

View file

@ -368,9 +368,16 @@ void PageView::keydown_event(GUI::KeyEvent& event)
event.accept(); event.accept();
} }
URL PageView::url() const
{
if (page().main_frame().document())
return {};
return page().main_frame().document()->url();
}
void PageView::reload() void PageView::reload()
{ {
load(page().main_frame().document()->url()); load(url());
} }
void PageView::load_html(const StringView& html, const URL& url) void PageView::load_html(const StringView& html, const URL& url)

View file

@ -43,6 +43,7 @@ WebContentView::~WebContentView()
void WebContentView::load(const URL& url) void WebContentView::load(const URL& url)
{ {
m_url = url;
client().post_message(Messages::WebContentServer::LoadURL(url)); client().post_message(Messages::WebContentServer::LoadURL(url));
} }

View file

@ -41,6 +41,7 @@ class WebContentView final
public: public:
virtual ~WebContentView() override; virtual ~WebContentView() override;
URL url() const { return m_url; }
void load(const URL&); void load(const URL&);
void notify_server_did_layout(Badge<WebContentClient>, const Gfx::IntSize& content_size); void notify_server_did_layout(Badge<WebContentClient>, const Gfx::IntSize& content_size);
@ -71,6 +72,8 @@ private:
WebContentClient& client(); WebContentClient& client();
URL m_url;
RefPtr<WebContentClient> m_client; RefPtr<WebContentClient> m_client;
RefPtr<Gfx::Bitmap> m_front_bitmap; RefPtr<Gfx::Bitmap> m_front_bitmap;
RefPtr<Gfx::Bitmap> m_back_bitmap; RefPtr<Gfx::Bitmap> m_back_bitmap;