PageHost.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*
  2. * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "PageHost.h"
  7. #include "ConnectionFromClient.h"
  8. #include <LibGfx/Painter.h>
  9. #include <LibGfx/ShareableBitmap.h>
  10. #include <LibGfx/SystemTheme.h>
  11. #include <LibWeb/Cookie/ParsedCookie.h>
  12. #include <LibWeb/HTML/BrowsingContext.h>
  13. #include <LibWeb/Layout/InitialContainingBlock.h>
  14. #include <LibWeb/Painting/PaintableBox.h>
  15. #include <WebContent/WebContentClientEndpoint.h>
  16. namespace WebContent {
  17. PageHost::PageHost(ConnectionFromClient& client)
  18. : m_client(client)
  19. , m_page(make<Web::Page>(*this))
  20. {
  21. setup_palette();
  22. m_invalidation_coalescing_timer = Core::Timer::create_single_shot(0, [this] {
  23. m_client.async_did_invalidate_content_rect(m_invalidation_rect);
  24. m_invalidation_rect = {};
  25. });
  26. }
  27. void PageHost::set_has_focus(bool has_focus)
  28. {
  29. m_has_focus = has_focus;
  30. }
  31. void PageHost::setup_palette()
  32. {
  33. // FIXME: Get the proper palette from our peer somehow
  34. auto buffer_or_error = Core::AnonymousBuffer::create_with_size(sizeof(Gfx::SystemTheme));
  35. VERIFY(!buffer_or_error.is_error());
  36. auto buffer = buffer_or_error.release_value();
  37. auto* theme = buffer.data<Gfx::SystemTheme>();
  38. theme->color[(int)Gfx::ColorRole::Window] = Color::Magenta;
  39. theme->color[(int)Gfx::ColorRole::WindowText] = Color::Cyan;
  40. m_palette_impl = Gfx::PaletteImpl::create_with_anonymous_buffer(buffer);
  41. }
  42. Gfx::Palette PageHost::palette() const
  43. {
  44. return Gfx::Palette(*m_palette_impl);
  45. }
  46. void PageHost::set_palette_impl(Gfx::PaletteImpl const& impl)
  47. {
  48. m_palette_impl = impl;
  49. if (auto* document = page().top_level_browsing_context().active_document())
  50. document->invalidate_style();
  51. }
  52. void PageHost::set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme)
  53. {
  54. m_preferred_color_scheme = color_scheme;
  55. if (auto* document = page().top_level_browsing_context().active_document())
  56. document->invalidate_style();
  57. }
  58. void PageHost::set_is_scripting_enabled(bool is_scripting_enabled)
  59. {
  60. page().set_is_scripting_enabled(is_scripting_enabled);
  61. }
  62. Web::Layout::InitialContainingBlock* PageHost::layout_root()
  63. {
  64. auto* document = page().top_level_browsing_context().active_document();
  65. if (!document)
  66. return nullptr;
  67. return document->layout_node();
  68. }
  69. void PageHost::paint(Gfx::IntRect const& content_rect, Gfx::Bitmap& target)
  70. {
  71. Gfx::Painter painter(target);
  72. Gfx::IntRect bitmap_rect { {}, content_rect.size() };
  73. if (auto* document = page().top_level_browsing_context().active_document())
  74. document->update_layout();
  75. auto* layout_root = this->layout_root();
  76. if (!layout_root) {
  77. painter.fill_rect(bitmap_rect, palette().base());
  78. return;
  79. }
  80. Web::PaintContext context(painter, palette(), content_rect.top_left());
  81. context.set_should_show_line_box_borders(m_should_show_line_box_borders);
  82. context.set_viewport_rect(content_rect);
  83. context.set_has_focus(m_has_focus);
  84. layout_root->paint_all_phases(context);
  85. }
  86. void PageHost::set_viewport_rect(Gfx::IntRect const& rect)
  87. {
  88. page().top_level_browsing_context().set_viewport_rect(rect);
  89. }
  90. void PageHost::page_did_invalidate(Gfx::IntRect const& content_rect)
  91. {
  92. m_invalidation_rect = m_invalidation_rect.united(content_rect);
  93. if (!m_invalidation_coalescing_timer->is_active())
  94. m_invalidation_coalescing_timer->start();
  95. }
  96. void PageHost::page_did_change_selection()
  97. {
  98. m_client.async_did_change_selection();
  99. }
  100. void PageHost::page_did_request_cursor_change(Gfx::StandardCursor cursor)
  101. {
  102. m_client.async_did_request_cursor_change((u32)cursor);
  103. }
  104. void PageHost::page_did_layout()
  105. {
  106. auto* layout_root = this->layout_root();
  107. VERIFY(layout_root);
  108. Gfx::IntSize content_size;
  109. if (layout_root->paint_box()->has_overflow())
  110. content_size = enclosing_int_rect(layout_root->paint_box()->scrollable_overflow_rect().value()).size();
  111. else
  112. content_size = enclosing_int_rect(layout_root->paint_box()->absolute_rect()).size();
  113. m_client.async_did_layout(content_size);
  114. }
  115. void PageHost::page_did_change_title(String const& title)
  116. {
  117. m_client.async_did_change_title(title);
  118. }
  119. void PageHost::page_did_request_scroll(i32 x_delta, i32 y_delta)
  120. {
  121. m_client.async_did_request_scroll(x_delta, y_delta);
  122. }
  123. void PageHost::page_did_request_scroll_to(Gfx::IntPoint const& scroll_position)
  124. {
  125. m_client.async_did_request_scroll_to(scroll_position);
  126. }
  127. void PageHost::page_did_request_scroll_into_view(Gfx::IntRect const& rect)
  128. {
  129. m_client.async_did_request_scroll_into_view(rect);
  130. }
  131. void PageHost::page_did_enter_tooltip_area(Gfx::IntPoint const& content_position, String const& title)
  132. {
  133. m_client.async_did_enter_tooltip_area(content_position, title);
  134. }
  135. void PageHost::page_did_leave_tooltip_area()
  136. {
  137. m_client.async_did_leave_tooltip_area();
  138. }
  139. void PageHost::page_did_hover_link(const URL& url)
  140. {
  141. m_client.async_did_hover_link(url);
  142. }
  143. void PageHost::page_did_unhover_link()
  144. {
  145. m_client.async_did_unhover_link();
  146. }
  147. void PageHost::page_did_click_link(const URL& url, String const& target, unsigned modifiers)
  148. {
  149. m_client.async_did_click_link(url, target, modifiers);
  150. }
  151. void PageHost::page_did_middle_click_link(const URL& url, [[maybe_unused]] String const& target, [[maybe_unused]] unsigned modifiers)
  152. {
  153. m_client.async_did_middle_click_link(url, target, modifiers);
  154. }
  155. void PageHost::page_did_start_loading(const URL& url)
  156. {
  157. m_client.async_did_start_loading(url);
  158. }
  159. void PageHost::page_did_create_main_document()
  160. {
  161. m_client.initialize_js_console({});
  162. }
  163. void PageHost::page_did_finish_loading(const URL& url)
  164. {
  165. m_client.async_did_finish_loading(url);
  166. }
  167. void PageHost::page_did_request_context_menu(Gfx::IntPoint const& content_position)
  168. {
  169. m_client.async_did_request_context_menu(content_position);
  170. }
  171. void PageHost::page_did_request_link_context_menu(Gfx::IntPoint const& content_position, const URL& url, String const& target, unsigned modifiers)
  172. {
  173. m_client.async_did_request_link_context_menu(content_position, url, target, modifiers);
  174. }
  175. void PageHost::page_did_request_alert(String const& message)
  176. {
  177. auto response = m_client.send_sync_but_allow_failure<Messages::WebContentClient::DidRequestAlert>(message);
  178. if (!response) {
  179. dbgln("WebContent client disconnected during DidRequestAlert. Exiting peacefully.");
  180. exit(0);
  181. }
  182. }
  183. bool PageHost::page_did_request_confirm(String const& message)
  184. {
  185. auto response = m_client.send_sync_but_allow_failure<Messages::WebContentClient::DidRequestConfirm>(message);
  186. if (!response) {
  187. dbgln("WebContent client disconnected during DidRequestConfirm. Exiting peacefully.");
  188. exit(0);
  189. }
  190. return response->take_result();
  191. }
  192. String PageHost::page_did_request_prompt(String const& message, String const& default_)
  193. {
  194. auto response = m_client.send_sync_but_allow_failure<Messages::WebContentClient::DidRequestPrompt>(message, default_);
  195. if (!response) {
  196. dbgln("WebContent client disconnected during DidRequestPrompt. Exiting peacefully.");
  197. exit(0);
  198. }
  199. return response->take_response();
  200. }
  201. void PageHost::page_did_change_favicon(Gfx::Bitmap const& favicon)
  202. {
  203. m_client.async_did_change_favicon(favicon.to_shareable_bitmap());
  204. }
  205. void PageHost::page_did_request_image_context_menu(Gfx::IntPoint const& content_position, const URL& url, String const& target, unsigned modifiers, Gfx::Bitmap const* bitmap_pointer)
  206. {
  207. auto bitmap = bitmap_pointer ? bitmap_pointer->to_shareable_bitmap() : Gfx::ShareableBitmap();
  208. m_client.async_did_request_image_context_menu(content_position, url, target, modifiers, bitmap);
  209. }
  210. String PageHost::page_did_request_cookie(const URL& url, Web::Cookie::Source source)
  211. {
  212. auto response = m_client.send_sync_but_allow_failure<Messages::WebContentClient::DidRequestCookie>(move(url), static_cast<u8>(source));
  213. if (!response) {
  214. dbgln("WebContent client disconnected during DidRequestCookie. Exiting peacefully.");
  215. exit(0);
  216. }
  217. return response->take_cookie();
  218. }
  219. void PageHost::page_did_set_cookie(const URL& url, Web::Cookie::ParsedCookie const& cookie, Web::Cookie::Source source)
  220. {
  221. m_client.async_did_set_cookie(url, cookie, static_cast<u8>(source));
  222. }
  223. void PageHost::page_did_update_resource_count(i32 count_waiting)
  224. {
  225. m_client.async_did_update_resource_count(count_waiting);
  226. }
  227. void PageHost::request_file(NonnullRefPtr<Web::FileRequest>& file_request)
  228. {
  229. m_client.request_file(file_request);
  230. }
  231. }