Window.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGUI/DisplayLink.h>
  7. #include <LibJS/Runtime/FunctionObject.h>
  8. #include <LibWeb/DOM/Document.h>
  9. #include <LibWeb/DOM/Event.h>
  10. #include <LibWeb/DOM/EventDispatcher.h>
  11. #include <LibWeb/DOM/Timer.h>
  12. #include <LibWeb/DOM/Window.h>
  13. #include <LibWeb/HighResolutionTime/Performance.h>
  14. #include <LibWeb/InProcessWebView.h>
  15. #include <LibWeb/Layout/InitialContainingBlockBox.h>
  16. #include <LibWeb/Page/BrowsingContext.h>
  17. namespace Web::DOM {
  18. NonnullRefPtr<Window> Window::create_with_document(Document& document)
  19. {
  20. return adopt_ref(*new Window(document));
  21. }
  22. Window::Window(Document& document)
  23. : EventTarget(static_cast<Bindings::ScriptExecutionContext&>(document))
  24. , m_document(document)
  25. , m_performance(make<HighResolutionTime::Performance>(*this))
  26. , m_screen(CSS::Screen::create(*this))
  27. {
  28. }
  29. Window::~Window()
  30. {
  31. }
  32. void Window::set_wrapper(Badge<Bindings::WindowObject>, Bindings::WindowObject& wrapper)
  33. {
  34. m_wrapper = wrapper.make_weak_ptr();
  35. }
  36. void Window::alert(const String& message)
  37. {
  38. if (auto* page = m_document.page())
  39. page->client().page_did_request_alert(message);
  40. }
  41. bool Window::confirm(const String& message)
  42. {
  43. if (auto* page = m_document.page())
  44. return page->client().page_did_request_confirm(message);
  45. return false;
  46. }
  47. String Window::prompt(const String& message, const String& default_)
  48. {
  49. if (auto* page = m_document.page())
  50. return page->client().page_did_request_prompt(message, default_);
  51. return {};
  52. }
  53. i32 Window::set_interval(JS::FunctionObject& callback, i32 interval)
  54. {
  55. auto timer = Timer::create_interval(*this, interval, callback);
  56. m_timers.set(timer->id(), timer);
  57. return timer->id();
  58. }
  59. i32 Window::set_timeout(JS::FunctionObject& callback, i32 interval)
  60. {
  61. auto timer = Timer::create_timeout(*this, interval, callback);
  62. m_timers.set(timer->id(), timer);
  63. return timer->id();
  64. }
  65. void Window::timer_did_fire(Badge<Timer>, Timer& timer)
  66. {
  67. // We should not be here if there's no JS wrapper for the Window object.
  68. VERIFY(wrapper());
  69. auto& vm = wrapper()->vm();
  70. // NOTE: This protector pointer keeps the timer alive until the end of this function no matter what.
  71. NonnullRefPtr protector(timer);
  72. if (timer.type() == Timer::Type::Timeout) {
  73. m_timers.remove(timer.id());
  74. }
  75. [[maybe_unused]] auto rc = vm.call(timer.callback(), wrapper());
  76. if (vm.exception())
  77. vm.clear_exception();
  78. }
  79. i32 Window::allocate_timer_id(Badge<Timer>)
  80. {
  81. return m_timer_id_allocator.allocate();
  82. }
  83. void Window::deallocate_timer_id(Badge<Timer>, i32 id)
  84. {
  85. m_timer_id_allocator.deallocate(id);
  86. }
  87. void Window::clear_timeout(i32 timer_id)
  88. {
  89. m_timers.remove(timer_id);
  90. }
  91. void Window::clear_interval(i32 timer_id)
  92. {
  93. m_timers.remove(timer_id);
  94. }
  95. i32 Window::request_animation_frame(JS::FunctionObject& callback)
  96. {
  97. // FIXME: This is extremely fake!
  98. static double fake_timestamp = 0;
  99. i32 link_id = GUI::DisplayLink::register_callback([handle = make_handle(&callback)](i32 link_id) {
  100. auto& function = const_cast<JS::FunctionObject&>(static_cast<const JS::FunctionObject&>(*handle.cell()));
  101. auto& vm = function.vm();
  102. fake_timestamp += 10;
  103. [[maybe_unused]] auto rc = vm.call(function, JS::js_undefined(), JS::Value(fake_timestamp));
  104. if (vm.exception())
  105. vm.clear_exception();
  106. GUI::DisplayLink::unregister_callback(link_id);
  107. });
  108. // FIXME: Don't hand out raw DisplayLink ID's to JavaScript!
  109. return link_id;
  110. }
  111. void Window::cancel_animation_frame(i32 id)
  112. {
  113. // FIXME: We should not be passing untrusted numbers to DisplayLink::unregister_callback()!
  114. GUI::DisplayLink::unregister_callback(id);
  115. }
  116. void Window::did_set_location_href(Badge<Bindings::LocationObject>, const URL& new_href)
  117. {
  118. auto* frame = document().browsing_context();
  119. if (!frame)
  120. return;
  121. frame->loader().load(new_href, FrameLoader::Type::Navigation);
  122. }
  123. void Window::did_call_location_reload(Badge<Bindings::LocationObject>)
  124. {
  125. auto* frame = document().browsing_context();
  126. if (!frame)
  127. return;
  128. frame->loader().load(document().url(), FrameLoader::Type::Reload);
  129. }
  130. bool Window::dispatch_event(NonnullRefPtr<Event> event)
  131. {
  132. return EventDispatcher::dispatch(*this, event, true);
  133. }
  134. JS::Object* Window::create_wrapper(JS::GlobalObject& global_object)
  135. {
  136. return &global_object;
  137. }
  138. int Window::inner_width() const
  139. {
  140. if (!document().layout_node())
  141. return 0;
  142. return document().layout_node()->width();
  143. }
  144. int Window::inner_height() const
  145. {
  146. if (!document().layout_node())
  147. return 0;
  148. return document().layout_node()->height();
  149. }
  150. }