LadybirdWebViewBridge.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. * Copyright (c) 2023-2024, Tim Flynn <trflynn89@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Interface/LadybirdWebViewBridge.h>
  7. #include <LibGfx/Font/FontDatabase.h>
  8. #include <LibGfx/Rect.h>
  9. #include <LibIPC/File.h>
  10. #include <LibWeb/Crypto/Crypto.h>
  11. #include <LibWebView/Application.h>
  12. #include <LibWebView/HelperProcess.h>
  13. #include <LibWebView/UserAgent.h>
  14. #include <LibWebView/Utilities.h>
  15. #import <Interface/Palette.h>
  16. namespace Ladybird {
  17. template<typename T>
  18. static T scale_for_device(T size, float device_pixel_ratio)
  19. {
  20. return size.template to_type<float>().scaled(device_pixel_ratio).template to_type<int>();
  21. }
  22. ErrorOr<NonnullOwnPtr<WebViewBridge>> WebViewBridge::create(Vector<Web::DevicePixelRect> screen_rects, float device_pixel_ratio, Web::CSS::PreferredColorScheme preferred_color_scheme, Web::CSS::PreferredContrast preferred_contrast, Web::CSS::PreferredMotion preferred_motion)
  23. {
  24. return adopt_nonnull_own_or_enomem(new (nothrow) WebViewBridge(move(screen_rects), device_pixel_ratio, preferred_color_scheme, preferred_contrast, preferred_motion));
  25. }
  26. WebViewBridge::WebViewBridge(Vector<Web::DevicePixelRect> screen_rects, float device_pixel_ratio, Web::CSS::PreferredColorScheme preferred_color_scheme, Web::CSS::PreferredContrast preferred_contrast, Web::CSS::PreferredMotion preferred_motion)
  27. : m_screen_rects(move(screen_rects))
  28. , m_preferred_color_scheme(preferred_color_scheme)
  29. , m_preferred_contrast(preferred_contrast)
  30. , m_preferred_motion(preferred_motion)
  31. {
  32. m_device_pixel_ratio = device_pixel_ratio;
  33. }
  34. WebViewBridge::~WebViewBridge() = default;
  35. void WebViewBridge::set_device_pixel_ratio(float device_pixel_ratio)
  36. {
  37. m_device_pixel_ratio = device_pixel_ratio;
  38. client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
  39. }
  40. void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect)
  41. {
  42. viewport_rect.set_size(scale_for_device(viewport_rect.size(), m_device_pixel_ratio));
  43. m_viewport_size = viewport_rect.size();
  44. handle_resize();
  45. }
  46. void WebViewBridge::update_palette()
  47. {
  48. auto theme = create_system_palette();
  49. client().async_update_system_theme(m_client_state.page_index, move(theme));
  50. }
  51. void WebViewBridge::set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme)
  52. {
  53. m_preferred_color_scheme = color_scheme;
  54. client().async_set_preferred_color_scheme(m_client_state.page_index, color_scheme);
  55. }
  56. void WebViewBridge::set_preferred_contrast(Web::CSS::PreferredContrast contrast)
  57. {
  58. m_preferred_contrast = contrast;
  59. client().async_set_preferred_contrast(m_client_state.page_index, contrast);
  60. }
  61. void WebViewBridge::set_preferred_motion(Web::CSS::PreferredMotion motion)
  62. {
  63. m_preferred_motion = motion;
  64. client().async_set_preferred_motion(m_client_state.page_index, motion);
  65. }
  66. void WebViewBridge::enqueue_input_event(Web::MouseEvent event)
  67. {
  68. event.position = to_content_position(event.position.to_type<int>()).to_type<Web::DevicePixels>();
  69. event.screen_position = to_content_position(event.screen_position.to_type<int>()).to_type<Web::DevicePixels>();
  70. ViewImplementation::enqueue_input_event(move(event));
  71. }
  72. void WebViewBridge::enqueue_input_event(Web::DragEvent event)
  73. {
  74. event.position = to_content_position(event.position.to_type<int>()).to_type<Web::DevicePixels>();
  75. event.screen_position = to_content_position(event.screen_position.to_type<int>()).to_type<Web::DevicePixels>();
  76. ViewImplementation::enqueue_input_event(move(event));
  77. }
  78. void WebViewBridge::enqueue_input_event(Web::KeyEvent event)
  79. {
  80. ViewImplementation::enqueue_input_event(move(event));
  81. }
  82. void WebViewBridge::set_enable_autoplay(bool enabled)
  83. {
  84. ViewImplementation::set_enable_autoplay(enabled);
  85. }
  86. Optional<WebViewBridge::Paintable> WebViewBridge::paintable()
  87. {
  88. Gfx::Bitmap* bitmap = nullptr;
  89. Gfx::IntSize bitmap_size;
  90. if (m_client_state.has_usable_bitmap) {
  91. bitmap = m_client_state.front_bitmap.bitmap.ptr();
  92. bitmap_size = m_client_state.front_bitmap.last_painted_size.to_type<int>();
  93. } else {
  94. bitmap = m_backup_bitmap.ptr();
  95. bitmap_size = m_backup_bitmap_size.to_type<int>();
  96. }
  97. if (!bitmap)
  98. return {};
  99. return Paintable { *bitmap, bitmap_size };
  100. }
  101. void WebViewBridge::update_zoom()
  102. {
  103. client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
  104. if (on_zoom_level_changed)
  105. on_zoom_level_changed();
  106. }
  107. Web::DevicePixelSize WebViewBridge::viewport_size() const
  108. {
  109. return m_viewport_size.to_type<Web::DevicePixels>();
  110. }
  111. Gfx::IntPoint WebViewBridge::to_content_position(Gfx::IntPoint widget_position) const
  112. {
  113. return scale_for_device(widget_position, m_device_pixel_ratio);
  114. }
  115. Gfx::IntPoint WebViewBridge::to_widget_position(Gfx::IntPoint content_position) const
  116. {
  117. return scale_for_device(content_position, inverse_device_pixel_ratio());
  118. }
  119. void WebViewBridge::initialize_client(CreateNewClient create_new_client)
  120. {
  121. if (create_new_client == CreateNewClient::Yes) {
  122. m_client_state = {};
  123. auto request_server_socket = WebView::connect_new_request_server_client().release_value_but_fixme_should_propagate_errors();
  124. auto image_decoder_socket = WebView::connect_new_image_decoder_client().release_value_but_fixme_should_propagate_errors();
  125. auto candidate_web_content_paths = WebView::get_paths_for_helper_process("WebContent"sv).release_value_but_fixme_should_propagate_errors();
  126. auto new_client = launch_web_content_process(*this, candidate_web_content_paths, AK::move(image_decoder_socket), AK::move(request_server_socket)).release_value_but_fixme_should_propagate_errors();
  127. m_client_state.client = new_client;
  128. } else {
  129. m_client_state.client->register_view(m_client_state.page_index, *this);
  130. }
  131. m_client_state.client->on_web_content_process_crash = [this] {
  132. Core::deferred_invoke([this] {
  133. handle_web_content_process_crash();
  134. });
  135. };
  136. m_client_state.client_handle = MUST(Web::Crypto::generate_random_uuid());
  137. client().async_set_window_handle(m_client_state.page_index, m_client_state.client_handle);
  138. client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio);
  139. client().async_set_preferred_color_scheme(m_client_state.page_index, m_preferred_color_scheme);
  140. set_system_visibility_state(m_system_visibility_state);
  141. update_palette();
  142. if (!m_screen_rects.is_empty()) {
  143. // FIXME: Update the screens again if they ever change.
  144. client().async_update_screen_rects(m_client_state.page_index, m_screen_rects, 0);
  145. }
  146. if (auto const& webdriver_content_ipc_path = WebView::Application::chrome_options().webdriver_content_ipc_path; webdriver_content_ipc_path.has_value()) {
  147. client().async_connect_to_webdriver(m_client_state.page_index, *webdriver_content_ipc_path);
  148. }
  149. if (auto const& user_agent_preset = WebView::Application::web_content_options().user_agent_preset; user_agent_preset.has_value()) {
  150. auto user_agent = *WebView::user_agents.get(*user_agent_preset);
  151. client().async_debug_request(m_client_state.page_index, "spoof-user-agent"sv, user_agent);
  152. }
  153. }
  154. void WebViewBridge::initialize_client_as_child(WebViewBridge const& parent, u64 page_index)
  155. {
  156. m_client_state.client = parent.client();
  157. m_client_state.page_index = page_index;
  158. initialize_client(CreateNewClient::No);
  159. }
  160. }