diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/script/dom/document.rs | 72 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/visibilitystateentry.rs | 73 | ||||
-rw-r--r-- | components/script/dom/webidls/Document.webidl | 3 | ||||
-rw-r--r-- | components/script/dom/webidls/VisibilityStateEntry.webidl | 13 |
5 files changed, 154 insertions, 8 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index ddf95e976cf..4f6d2ab0354 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -67,7 +67,6 @@ use url::Host; use uuid::Uuid; use webrender_api::units::DeviceIntRect; -use super::bindings::trace::{HashMapTracedValues, NoTrace}; use crate::animation_timeline::AnimationTimeline; use crate::animations::Animations; use crate::document_loader::{DocumentLoader, LoadType}; @@ -77,7 +76,7 @@ use crate::dom::bindings::callback::ExceptionHandling; use crate::dom::bindings::cell::{ref_filter_map, DomRefCell, Ref, RefMut}; use crate::dom::bindings::codegen::Bindings::BeforeUnloadEventBinding::BeforeUnloadEvent_Binding::BeforeUnloadEventMethods; use crate::dom::bindings::codegen::Bindings::DocumentBinding::{ - DocumentMethods, DocumentReadyState, NamedPropertyValue, + DocumentMethods, DocumentReadyState, DocumentVisibilityState, NamedPropertyValue, }; use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods; use crate::dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElement_Binding::HTMLIFrameElementMethods; @@ -100,6 +99,7 @@ use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, DomObject}; use crate::dom::bindings::root::{Dom, DomRoot, DomSlice, LayoutDom, MutNullableDom}; use crate::dom::bindings::str::{DOMString, USVString}; +use crate::dom::bindings::trace::{HashMapTracedValues, NoTrace}; use crate::dom::bindings::xmlname::XMLName::Invalid; use crate::dom::bindings::xmlname::{ namespace_from_domstring, validate_and_extract, xml_name_type, @@ -153,6 +153,7 @@ use crate::dom::node::{ use crate::dom::nodeiterator::NodeIterator; use crate::dom::nodelist::NodeList; use crate::dom::pagetransitionevent::PageTransitionEvent; +use crate::dom::performanceentry::PerformanceEntry; use crate::dom::processinginstruction::ProcessingInstruction; use crate::dom::promise::Promise; use crate::dom::range::Range; @@ -167,6 +168,7 @@ use crate::dom::touch::Touch; use crate::dom::touchevent::TouchEvent; use crate::dom::touchlist::TouchList; use crate::dom::treewalker::TreeWalker; +use crate::dom::types::VisibilityStateEntry; use crate::dom::uievent::UIEvent; use crate::dom::virtualmethods::vtable_for; use crate::dom::webglrenderingcontext::WebGLRenderingContext; @@ -470,6 +472,8 @@ pub struct Document { /// The set of all fonts loaded by this document. /// <https://drafts.csswg.org/css-font-loading/#font-face-source> fonts: MutNullableDom<FontFaceSet>, + /// <https://html.spec.whatwg.org/multipage/#visibility-state> + visibility_state: Cell<DocumentVisibilityState>, } #[derive(JSTraceable, MallocSizeOf)] @@ -708,8 +712,9 @@ impl Document { return; } - // html.spec.whatwg.org/multipage/#history-traversal - // Step 4.6 + // This step used to be Step 4.6 in html.spec.whatwg.org/multipage/#history-traversal + // But it's now Step 4 in https://html.spec.whatwg.org/multipage/#reactivate-a-document + // TODO: See #32687 for more information. let document = Trusted::new(self); self.window .task_manager() @@ -722,9 +727,12 @@ impl Document { if document.page_showing.get() { return; } - // Step 4.6.2 + // Step 4.6.2 Set document's page showing flag to true. document.page_showing.set(true); - // Step 4.6.4 + // Step 4.6.3 Update the visibility state of document to "visible". + document.update_visibility_state(DocumentVisibilityState::Visible); + // Step 4.6.4 Fire a page transition event named pageshow at document's relevant + // global object with true. let event = PageTransitionEvent::new( window, atom!("pageshow"), @@ -2220,9 +2228,12 @@ impl Document { // TODO: Step 1, increase the event loop's termination nesting level by 1. // Step 2 self.incr_ignore_opens_during_unload_counter(); - // Step 3-6 + // Step 3-6 If oldDocument's page showing is true: if self.page_showing.get() { + // Set oldDocument's page showing to false. self.page_showing.set(false); + // Fire a page transition event named pagehide at oldDocument's relevant global object with oldDocument's + // salvageable state. let event = PageTransitionEvent::new( &self.window, atom!("pagehide"), @@ -2233,7 +2244,8 @@ impl Document { let event = event.upcast::<Event>(); event.set_trusted(true); let _ = self.window.dispatch_event_with_target_override(event); - // TODO Step 6, document visibility steps. + // Step 6 Update the visibility state of oldDocument to "hidden". + self.update_visibility_state(DocumentVisibilityState::Hidden); } // Step 7 if !self.fired_unload.get() { @@ -3297,6 +3309,7 @@ impl Document { mouse_move_event_index: Default::default(), resize_observers: Default::default(), fonts: Default::default(), + visibility_state: Cell::new(DocumentVisibilityState::Hidden), } } @@ -4083,6 +4096,39 @@ impl Document { pub(crate) fn set_declarative_refresh(&self, refresh: DeclarativeRefresh) { *self.declarative_refresh.borrow_mut() = Some(refresh); } + + /// <https://html.spec.whatwg.org/multipage/#visibility-state> + fn update_visibility_state(&self, visibility_state: DocumentVisibilityState) { + // Step 1 If document's visibility state equals visibilityState, then return. + if self.visibility_state.get() == visibility_state { + return; + } + // Step 2 Set document's visibility state to visibilityState. + self.visibility_state.set(visibility_state); + // Step 3 Queue a new VisibilityStateEntry whose visibility state is visibilityState and whose timestamp is + // the current high resolution time given document's relevant global object. + let entry = VisibilityStateEntry::new( + &self.global(), + visibility_state, + *self.global().performance().Now(), + ); + self.window + .Performance() + .queue_entry(entry.upcast::<PerformanceEntry>()); + + // Step 4 Run the screen orientation change steps with document. + // TODO ScreenOrientation hasn't implemented yet + + // Step 5 Run the view transition page visibility change steps with document. + // TODO ViewTransition hasn't implemented yet + + // Step 6 Run any page visibility change steps which may be defined in other specifications, with visibility + // state and document. Any other specs' visibility steps will go here. + + // Step 7 Fire an event named visibilitychange at document, with its bubbles attribute initialized to true. + self.upcast::<EventTarget>() + .fire_bubbling_event(atom!("visibilitychange")); + } } impl ProfilerMetadataFactory for Document { @@ -5376,6 +5422,16 @@ impl DocumentMethods for Document { self.fonts .or_init(|| FontFaceSet::new(&self.global(), None)) } + + /// <https://html.spec.whatwg.org/multipage/#dom-document-hidden> + fn Hidden(&self) -> bool { + self.visibility_state.get() == DocumentVisibilityState::Hidden + } + + /// <https://html.spec.whatwg.org/multipage/#dom-document-visibilitystate> + fn VisibilityState(&self) -> DocumentVisibilityState { + self.visibility_state.get() + } } fn update_with_current_time_ms(marker: &Cell<u64>) { diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index a4c4f2f3230..76723e8f2ce 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -580,6 +580,7 @@ pub mod vertexarrayobject; pub mod videotrack; pub mod videotracklist; pub mod virtualmethods; +pub mod visibilitystateentry; pub mod vttcue; pub mod vttregion; pub mod webgl2renderingcontext; diff --git a/components/script/dom/visibilitystateentry.rs b/components/script/dom/visibilitystateentry.rs new file mode 100644 index 00000000000..9dcf74a58e6 --- /dev/null +++ b/components/script/dom/visibilitystateentry.rs @@ -0,0 +1,73 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use std::ops::Deref; + +use dom_struct::dom_struct; + +use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentVisibilityState; +use crate::dom::bindings::codegen::Bindings::PerformanceEntryBinding::PerformanceEntryMethods; +use crate::dom::bindings::codegen::Bindings::VisibilityStateEntryBinding::VisibilityStateEntryMethods; +use crate::dom::bindings::num::Finite; +use crate::dom::bindings::reflector::reflect_dom_object; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use crate::dom::performanceentry::PerformanceEntry; + +#[dom_struct] +pub struct VisibilityStateEntry { + entry: PerformanceEntry, +} + +impl VisibilityStateEntry { + #[allow(crown::unrooted_must_root)] + fn new_inherited(state: DocumentVisibilityState, timestamp: f64) -> VisibilityStateEntry { + let name = match state { + DocumentVisibilityState::Visible => DOMString::from("visible"), + DocumentVisibilityState::Hidden => DOMString::from("hidden"), + }; + VisibilityStateEntry { + entry: PerformanceEntry::new_inherited( + name, + DOMString::from("visibility-state"), + timestamp, + 0., + ), + } + } + + pub fn new( + global: &GlobalScope, + state: DocumentVisibilityState, + timestamp: f64, + ) -> DomRoot<VisibilityStateEntry> { + reflect_dom_object( + Box::new(VisibilityStateEntry::new_inherited(state, timestamp)), + global, + ) + } +} + +impl VisibilityStateEntryMethods for VisibilityStateEntry { + /// <https://html.spec.whatwg.org/multipage/#visibilitystateentry-name> + fn Name(&self) -> DOMString { + self.entry.Name() + } + + /// <https://html.spec.whatwg.org/multipage/#visibilitystateentry-entrytype> + fn EntryType(&self) -> DOMString { + self.entry.EntryType() + } + + /// <https://html.spec.whatwg.org/multipage/#visibilitystateentry-starttime> + fn StartTime(&self) -> Finite<f64> { + self.entry.StartTime() + } + + /// <https://html.spec.whatwg.org/multipage/#visibilitystateentry-duration> + fn Duration(&self) -> u32 { + *self.entry.Duration().deref() as u32 + } +} diff --git a/components/script/dom/webidls/Document.webidl b/components/script/dom/webidls/Document.webidl index 00cc5d81506..6131dbd15c7 100644 --- a/components/script/dom/webidls/Document.webidl +++ b/components/script/dom/webidls/Document.webidl @@ -78,6 +78,7 @@ Document includes NonElementParentNode; Document includes ParentNode; enum DocumentReadyState { "loading", "interactive", "complete" }; +enum DocumentVisibilityState { "visible", "hidden" }; dictionary ElementCreationOptions { DOMString is; @@ -144,6 +145,8 @@ partial /*sealed*/ interface Document { // boolean queryCommandState(DOMString commandId); boolean queryCommandSupported(DOMString commandId); // DOMString queryCommandValue(DOMString commandId); + readonly attribute boolean hidden; + readonly attribute DocumentVisibilityState visibilityState; // special event handler IDL attributes that only apply to Document objects [LegacyLenientThis] attribute EventHandler onreadystatechange; diff --git a/components/script/dom/webidls/VisibilityStateEntry.webidl b/components/script/dom/webidls/VisibilityStateEntry.webidl new file mode 100644 index 00000000000..12e85541be5 --- /dev/null +++ b/components/script/dom/webidls/VisibilityStateEntry.webidl @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// https://html.spec.whatwg.org/multipage/#visibilitystateentry + +[Exposed=(Window)] +interface VisibilityStateEntry : PerformanceEntry { + readonly attribute DOMString name; // shadows inherited name + readonly attribute DOMString entryType; // shadows inherited entryType + readonly attribute DOMHighResTimeStamp startTime; // shadows inherited startTime + readonly attribute unsigned long duration; // shadows inherited duration +}; |