/* * Copyright (c) 2020-2024, Andreas Kling * Copyright (c) 2021-2023, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Web::HTML { class IdleCallback; // https://w3c.github.io/csswg-drafts/cssom-view/#dictdef-scrolltooptions struct ScrollToOptions : public ScrollOptions { Optional left; Optional top; }; // https://html.spec.whatwg.org/multipage/nav-history-apis.html#windowpostmessageoptions struct WindowPostMessageOptions : public StructuredSerializeOptions { String target_origin { "/"_string }; }; // https://html.spec.whatwg.org/multipage/webappapis.html#specifier-resolution-record // A specifier resolution record is a struct. It has the following items: struct SpecifierResolution { // A serialized base URL // A string-or-null that represents the base URL of the specifier, when one exists. Optional serialized_base_url; // A specifier // A string representing the specifier. String specifier; // A specifier as a URL // A URL-or-null that represents the URL in case of a URL-like module specifier. // // Spec-Note: Implementations can replace specifier as a URL with a boolean that indicates // that the specifier is either bare or URL-like that is special. bool specifier_is_null_or_url_like_that_is_special { false }; }; class Window final : public DOM::EventTarget , public GlobalEventHandlers , public WindowEventHandlers , public WindowOrWorkerGlobalScopeMixin , public UniversalGlobalScopeMixin , public Bindings::WindowGlobalMixin { WEB_PLATFORM_OBJECT(Window, DOM::EventTarget); GC_DECLARE_ALLOCATOR(Window); public: [[nodiscard]] static GC::Ref create(JS::Realm&); ~Window(); using UniversalGlobalScopeMixin::atob; using UniversalGlobalScopeMixin::btoa; using UniversalGlobalScopeMixin::queue_microtask; using UniversalGlobalScopeMixin::structured_clone; using WindowOrWorkerGlobalScopeMixin::clear_interval; using WindowOrWorkerGlobalScopeMixin::clear_timeout; using WindowOrWorkerGlobalScopeMixin::create_image_bitmap; using WindowOrWorkerGlobalScopeMixin::fetch; using WindowOrWorkerGlobalScopeMixin::report_error; using WindowOrWorkerGlobalScopeMixin::set_interval; using WindowOrWorkerGlobalScopeMixin::set_timeout; // ^DOM::EventTarget virtual bool dispatch_event(DOM::Event&) override; // ^WindowOrWorkerGlobalScopeMixin virtual DOM::EventTarget& this_impl() override { return *this; } virtual DOM::EventTarget const& this_impl() const override { return *this; } // ^JS::Object virtual JS::ThrowCompletionOr internal_set_prototype_of(JS::Object* prototype) override; Page& page(); Page const& page() const; // https://html.spec.whatwg.org/multipage/window-object.html#concept-document-window DOM::Document const& associated_document() const { return *m_associated_document; } DOM::Document& associated_document() { return *m_associated_document; } void set_associated_document(DOM::Document&); // https://html.spec.whatwg.org/multipage/window-object.html#window-bc BrowsingContext const* browsing_context() const; BrowsingContext* browsing_context(); GC::Ptr navigable() const; ImportMap& import_map() { return m_import_map; } ImportMap const& import_map() const { return m_import_map; } void set_import_map(ImportMap const& import_map) { m_import_map = import_map; } void append_resolved_module(SpecifierResolution resolution) { m_resolved_module_set.append(move(resolution)); } Vector const& resolved_module_set() const { return m_resolved_module_set; } WebIDL::ExceptionOr> window_open_steps(StringView url, StringView target, StringView features); struct OpenedWindow { GC::Ptr navigable; TokenizedFeature::NoOpener no_opener { TokenizedFeature::NoOpener::No }; Navigable::WindowType window_type { Navigable::WindowType::ExistingOrNone }; }; WebIDL::ExceptionOr window_open_steps_internal(StringView url, StringView target, StringView features); DOM::Event* current_event() { return m_current_event.ptr(); } DOM::Event const* current_event() const { return m_current_event.ptr(); } void set_current_event(DOM::Event* event); Optional query_media_feature(CSS::MediaFeatureID) const; void fire_a_page_transition_event(FlyString const& event_name, bool persisted); WebIDL::ExceptionOr> local_storage(); WebIDL::ExceptionOr> session_storage(); void start_an_idle_period(); // https://html.spec.whatwg.org/multipage/interaction.html#sticky-activation bool has_sticky_activation() const; // https://html.spec.whatwg.org/multipage/interaction.html#transient-activation bool has_transient_activation() const; // https://html.spec.whatwg.org/multipage/interaction.html#history-action-activation bool has_history_action_activation() const; WebIDL::ExceptionOr initialize_web_interfaces(Badge); Vector> pdf_viewer_plugin_objects(); Vector> pdf_viewer_mime_type_objects(); CrossOriginPropertyDescriptorMap const& cross_origin_property_descriptor_map() const { return m_cross_origin_property_descriptor_map; } CrossOriginPropertyDescriptorMap& cross_origin_property_descriptor_map() { return m_cross_origin_property_descriptor_map; } // JS API functions GC::Ref window() const; GC::Ref self() const; GC::Ref document() const; String name() const; void set_name(String const&); String status() const; void close(); bool closed() const; void set_status(String const&); [[nodiscard]] GC::Ref location(); GC::Ref history() const; GC::Ref navigation(); void stop(); void focus(); void blur(); GC::Ref frames() const; u32 length(); GC::Ptr top() const; GC::Ptr opener() const; WebIDL::ExceptionOr set_opener(JS::Value); GC::Ptr parent() const; GC::Ptr frame_element() const; WebIDL::ExceptionOr> open(Optional const& url, Optional const& target, Optional const& features); [[nodiscard]] GC::Ref navigator(); [[nodiscard]] GC::Ref close_watcher_manager(); void alert(String const& message = {}); bool confirm(Optional const& message); Optional prompt(Optional const& message, Optional const& default_); WebIDL::ExceptionOr post_message(JS::Value message, String const&, Vector> const&); WebIDL::ExceptionOr post_message(JS::Value message, WindowPostMessageOptions const&); Variant, JS::Value> event() const; [[nodiscard]] GC::Ref get_computed_style(DOM::Element&, Optional const& pseudo_element) const; WebIDL::ExceptionOr> match_media(String const& query); [[nodiscard]] GC::Ref screen(); [[nodiscard]] GC::Ptr visual_viewport(); i32 inner_width() const; i32 inner_height() const; void move_to(long, long) const; void move_by(long, long) const; void resize_to(long, long) const; void resize_by(long, long) const; double scroll_x() const; double scroll_y() const; void scroll(ScrollToOptions const&); void scroll(double x, double y); void scroll_by(ScrollToOptions); void scroll_by(double x, double y); i32 screen_x() const; i32 screen_y() const; i32 outer_width() const; i32 outer_height() const; double device_pixel_ratio() const; AnimationFrameCallbackDriver& animation_frame_callback_driver(); bool has_animation_frame_callbacks(); WebIDL::UnsignedLong request_animation_frame(GC::Ref); void cancel_animation_frame(WebIDL::UnsignedLong handle); u32 request_idle_callback(WebIDL::CallbackType&, RequestIdleCallback::IdleRequestOptions const&); void cancel_idle_callback(u32 handle); GC::Ptr get_selection() const; void capture_events(); void release_events(); [[nodiscard]] GC::Ref custom_elements(); HighResolutionTime::DOMHighResTimeStamp last_activation_timestamp() const { return m_last_activation_timestamp; } void set_last_activation_timestamp(HighResolutionTime::DOMHighResTimeStamp timestamp) { m_last_activation_timestamp = timestamp; } void consume_user_activation(); HighResolutionTime::DOMHighResTimeStamp last_history_action_activation_timestamp() const { return m_last_history_action_activation_timestamp; } void set_last_history_action_activation_timestamp(HighResolutionTime::DOMHighResTimeStamp timestamp) { m_last_history_action_activation_timestamp = timestamp; } void consume_history_action_user_activation(); static void set_inspector_object_exposed(bool); static void set_internals_object_exposed(bool); [[nodiscard]] OrderedHashMap> document_tree_child_navigable_target_name_property_set(); [[nodiscard]] Vector supported_property_names() const override; [[nodiscard]] JS::Value named_item_value(FlyString const&) const override; bool find(String const& string); private: explicit Window(JS::Realm&); virtual void visit_edges(Cell::Visitor&) override; virtual void finalize() override; // ^HTML::GlobalEventHandlers virtual GC::Ptr global_event_handlers_to_event_target(FlyString const&) override { return *this; } // ^HTML::WindowEventHandlers virtual GC::Ptr window_event_handlers_to_event_target() override { return *this; } void invoke_idle_callbacks(); struct [[nodiscard]] NamedObjects { Vector> navigables; Vector> elements; }; NamedObjects named_objects(StringView name); WebIDL::ExceptionOr window_post_message_steps(JS::Value, WindowPostMessageOptions const&); // https://html.spec.whatwg.org/multipage/window-object.html#concept-document-window GC::Ptr m_associated_document; GC::Ptr m_current_event; // https://html.spec.whatwg.org/multipage/webappapis.html#concept-global-import-map // A global object has an import map, initially an empty import map. ImportMap m_import_map; // https://html.spec.whatwg.org/multipage/webappapis.html#resolved-module-set // A global object has a resolved module set, a set of specifier resolution records, initially empty. // // Spec-Note: The resolved module set ensures that module specifier resolution returns the same result when called // multiple times with the same (referrer, specifier) pair. It does that by ensuring that import map rules // that impact the specifier in its referrer's scope cannot be defined after its initial resolution. For // now, only Window global objects have their module set data structures modified from the initial empty one. Vector m_resolved_module_set; GC::Ptr m_screen; GC::Ptr m_navigator; GC::Ptr m_location; GC::Ptr m_close_watcher_manager; // https://html.spec.whatwg.org/multipage/nav-history-apis.html#window-navigation-api GC::Ptr m_navigation; // https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-api // Each Window object has an associated custom element registry (a CustomElementRegistry object). // It is set to a new CustomElementRegistry object when the Window object is created. GC::Ptr m_custom_element_registry; GC::Ptr m_animation_frame_callback_driver; // https://w3c.github.io/requestidlecallback/#dfn-list-of-idle-request-callbacks Vector> m_idle_request_callbacks; // https://w3c.github.io/requestidlecallback/#dfn-list-of-runnable-idle-callbacks Vector> m_runnable_idle_callbacks; // https://w3c.github.io/requestidlecallback/#dfn-idle-callback-identifier u32 m_idle_callback_identifier = 0; // https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-plugin-objects Vector> m_pdf_viewer_plugin_objects; // https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-mime-type-objects Vector> m_pdf_viewer_mime_type_objects; // [[CrossOriginPropertyDescriptorMap]], https://html.spec.whatwg.org/multipage/browsers.html#crossoriginpropertydescriptormap CrossOriginPropertyDescriptorMap m_cross_origin_property_descriptor_map; // https://html.spec.whatwg.org/multipage/interaction.html#user-activation-data-model HighResolutionTime::DOMHighResTimeStamp m_last_activation_timestamp { AK::Infinity }; // https://html.spec.whatwg.org/multipage/interaction.html#last-history-action-activation-timestamp HighResolutionTime::DOMHighResTimeStamp m_last_history_action_activation_timestamp { AK::Infinity }; // https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-status // When the Window object is created, the attribute must be set to the empty string. It does not do anything else. String m_status; }; void run_animation_frame_callbacks(DOM::Document&, double now); }