Internals.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (c) 2023, Andreas Kling <andreas@ladybird.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Runtime/VM.h>
  7. #include <LibWeb/Bindings/InternalsPrototype.h>
  8. #include <LibWeb/Bindings/Intrinsics.h>
  9. #include <LibWeb/DOM/Document.h>
  10. #include <LibWeb/DOM/Event.h>
  11. #include <LibWeb/DOM/EventTarget.h>
  12. #include <LibWeb/DOMURL/DOMURL.h>
  13. #include <LibWeb/HTML/HTMLElement.h>
  14. #include <LibWeb/HTML/Window.h>
  15. #include <LibWeb/Internals/Internals.h>
  16. #include <LibWeb/Page/InputEvent.h>
  17. #include <LibWeb/Page/Page.h>
  18. #include <LibWeb/Painting/PaintableBox.h>
  19. #include <LibWeb/Painting/ViewportPaintable.h>
  20. namespace Web::Internals {
  21. GC_DEFINE_ALLOCATOR(Internals);
  22. Internals::Internals(JS::Realm& realm)
  23. : Bindings::PlatformObject(realm)
  24. {
  25. }
  26. Internals::~Internals() = default;
  27. void Internals::initialize(JS::Realm& realm)
  28. {
  29. Base::initialize(realm);
  30. WEB_SET_PROTOTYPE_FOR_INTERFACE(Internals);
  31. }
  32. HTML::Window& Internals::internals_window() const
  33. {
  34. return verify_cast<HTML::Window>(HTML::relevant_global_object(*this));
  35. }
  36. Page& Internals::internals_page() const
  37. {
  38. return internals_window().page();
  39. }
  40. void Internals::signal_text_test_is_done(String const& text)
  41. {
  42. internals_page().client().page_did_finish_text_test(text);
  43. }
  44. void Internals::gc()
  45. {
  46. vm().heap().collect_garbage();
  47. }
  48. JS::Object* Internals::hit_test(double x, double y)
  49. {
  50. auto& active_document = internals_window().associated_document();
  51. // NOTE: Force a layout update just before hit testing. This is because the current layout tree, which is required
  52. // for stacking context traversal, might not exist if this call occurs between the tear_down_layout_tree()
  53. // and update_layout() calls
  54. active_document.update_layout();
  55. auto result = active_document.paintable_box()->hit_test({ x, y }, Painting::HitTestType::Exact);
  56. if (result.has_value()) {
  57. auto hit_tеsting_result = JS::Object::create(realm(), nullptr);
  58. hit_tеsting_result->define_direct_property("node", result->dom_node(), JS::default_attributes);
  59. hit_tеsting_result->define_direct_property("indexInNode", JS::Value(result->index_in_node), JS::default_attributes);
  60. return hit_tеsting_result;
  61. }
  62. return nullptr;
  63. }
  64. void Internals::send_text(HTML::HTMLElement& target, String const& text, WebIDL::UnsignedShort modifiers)
  65. {
  66. auto& page = internals_page();
  67. target.focus();
  68. for (auto code_point : text.code_points())
  69. page.handle_keydown(UIEvents::code_point_to_key_code(code_point), modifiers, code_point, false);
  70. }
  71. void Internals::send_key(HTML::HTMLElement& target, String const& key_name, WebIDL::UnsignedShort modifiers)
  72. {
  73. auto key_code = UIEvents::key_code_from_string(key_name);
  74. target.focus();
  75. internals_page().handle_keydown(key_code, modifiers, 0, false);
  76. }
  77. void Internals::commit_text()
  78. {
  79. internals_page().handle_keydown(UIEvents::Key_Return, 0, 0, false);
  80. }
  81. void Internals::click(double x, double y)
  82. {
  83. click(x, y, UIEvents::MouseButton::Primary);
  84. }
  85. void Internals::doubleclick(double x, double y)
  86. {
  87. auto& page = internals_page();
  88. auto position = page.css_to_device_point({ x, y });
  89. page.handle_doubleclick(position, position, UIEvents::MouseButton::Primary, 0, 0);
  90. }
  91. void Internals::middle_click(double x, double y)
  92. {
  93. click(x, y, UIEvents::MouseButton::Middle);
  94. }
  95. void Internals::click(double x, double y, UIEvents::MouseButton button)
  96. {
  97. auto& page = internals_page();
  98. auto position = page.css_to_device_point({ x, y });
  99. page.handle_mousedown(position, position, button, 0, 0);
  100. page.handle_mouseup(position, position, button, 0, 0);
  101. }
  102. void Internals::move_pointer_to(double x, double y)
  103. {
  104. auto& page = internals_page();
  105. auto position = page.css_to_device_point({ x, y });
  106. page.handle_mousemove(position, position, 0, 0);
  107. }
  108. void Internals::wheel(double x, double y, double delta_x, double delta_y)
  109. {
  110. auto& page = internals_page();
  111. auto position = page.css_to_device_point({ x, y });
  112. page.handle_mousewheel(position, position, 0, 0, 0, delta_x, delta_y);
  113. }
  114. WebIDL::ExceptionOr<bool> Internals::dispatch_user_activated_event(DOM::EventTarget& target, DOM::Event& event)
  115. {
  116. event.set_is_trusted(true);
  117. return target.dispatch_event(event);
  118. }
  119. void Internals::spoof_current_url(String const& url_string)
  120. {
  121. auto url = DOMURL::parse(url_string);
  122. VERIFY(url.is_valid());
  123. auto origin = url.origin();
  124. auto& window = internals_window();
  125. window.associated_document().set_url(url);
  126. window.associated_document().set_origin(origin);
  127. HTML::relevant_settings_object(window.associated_document()).creation_url = url;
  128. }
  129. GC::Ref<InternalAnimationTimeline> Internals::create_internal_animation_timeline()
  130. {
  131. auto& realm = this->realm();
  132. return realm.create<InternalAnimationTimeline>(realm);
  133. }
  134. void Internals::simulate_drag_start(double x, double y, String const& name, String const& contents)
  135. {
  136. Vector<HTML::SelectedFile> files;
  137. files.empend(name.to_byte_string(), MUST(ByteBuffer::copy(contents.bytes())));
  138. auto& page = internals_page();
  139. auto position = page.css_to_device_point({ x, y });
  140. page.handle_drag_and_drop_event(DragEvent::Type::DragStart, position, position, UIEvents::MouseButton::Primary, 0, 0, move(files));
  141. }
  142. void Internals::simulate_drag_move(double x, double y)
  143. {
  144. auto& page = internals_page();
  145. auto position = page.css_to_device_point({ x, y });
  146. page.handle_drag_and_drop_event(DragEvent::Type::DragMove, position, position, UIEvents::MouseButton::Primary, 0, 0, {});
  147. }
  148. void Internals::simulate_drop(double x, double y)
  149. {
  150. auto& page = internals_page();
  151. auto position = page.css_to_device_point({ x, y });
  152. page.handle_drag_and_drop_event(DragEvent::Type::Drop, position, position, UIEvents::MouseButton::Primary, 0, 0, {});
  153. }
  154. void Internals::enable_cookies_on_file_domains()
  155. {
  156. internals_window().associated_document().enable_cookies_on_file_domains({});
  157. }
  158. void Internals::expire_cookies_with_time_offset(WebIDL::LongLong seconds)
  159. {
  160. internals_page().client().page_did_expire_cookies_with_time_offset(AK::Duration::from_seconds(seconds));
  161. }
  162. String Internals::get_computed_label(DOM::Element& element)
  163. {
  164. auto& active_document = internals_window().associated_document();
  165. return MUST(element.accessible_name(active_document));
  166. }
  167. }