diff options
author | Alan Jeffrey <ajeffrey@mozilla.com> | 2017-01-10 14:35:25 -0600 |
---|---|---|
committer | Alan Jeffrey <ajeffrey@mozilla.com> | 2017-01-27 12:39:43 -0600 |
commit | a43c842099019c9193b6cddfa5219ddbc8b93eee (patch) | |
tree | be613e3f373897aba1a1033f50d5cd0702451fa7 /components/script | |
parent | 556a46f537009bfc0c5cffadcd1a640c2b0c3029 (diff) | |
download | servo-a43c842099019c9193b6cddfa5219ddbc8b93eee.tar.gz servo-a43c842099019c9193b6cddfa5219ddbc8b93eee.zip |
The constellation notifies the script thread about documents becoming inactive, active and fully active.
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 4 | ||||
-rw-r--r-- | components/script/dom/document.rs | 48 | ||||
-rw-r--r-- | components/script/dom/domimplementation.rs | 3 | ||||
-rw-r--r-- | components/script/dom/domparser.rs | 3 | ||||
-rw-r--r-- | components/script/dom/node.rs | 4 | ||||
-rw-r--r-- | components/script/dom/servoparser/mod.rs | 2 | ||||
-rw-r--r-- | components/script/dom/window.rs | 10 | ||||
-rw-r--r-- | components/script/dom/xmldocument.rs | 5 | ||||
-rw-r--r-- | components/script/dom/xmlhttprequest.rs | 2 | ||||
-rw-r--r-- | components/script/script_thread.rs | 52 | ||||
-rw-r--r-- | components/script/timers.rs | 4 |
11 files changed, 76 insertions, 61 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 6d268823d77..6e0ce0d47dc 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -74,7 +74,7 @@ use profile_traits::time::ProfilerChan as TimeProfilerChan; use script_layout_interface::OpaqueStyleAndLayoutData; use script_layout_interface::reporter::CSSErrorReporter; use script_layout_interface::rpc::LayoutRPC; -use script_traits::{TimerEventId, TimerSource, TouchpadPressurePhase}; +use script_traits::{DocumentActivity, TimerEventId, TimerSource, TouchpadPressurePhase}; use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType}; use serde::{Deserialize, Serialize}; use servo_atoms::Atom; @@ -327,7 +327,7 @@ unsafe_no_jsmanaged_fields!(TrustedPromise); unsafe_no_jsmanaged_fields!(PropertyDeclarationBlock); // These three are interdependent, if you plan to put jsmanaged data // in one of these make sure it is propagated properly to containing structs -unsafe_no_jsmanaged_fields!(FrameId, FrameType, WindowSizeData, WindowSizeType, PipelineId); +unsafe_no_jsmanaged_fields!(DocumentActivity, FrameId, FrameType, WindowSizeData, WindowSizeType, PipelineId); unsafe_no_jsmanaged_fields!(TimerEventId, TimerSource); unsafe_no_jsmanaged_fields!(TimelineMarkerType); unsafe_no_jsmanaged_fields!(WorkerId); diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 692c24f052a..10ce0f3bf28 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -108,7 +108,8 @@ use origin::Origin; use script_layout_interface::message::{Msg, ReflowQueryType}; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; use script_thread::{MainThreadScriptMsg, Runnable}; -use script_traits::{AnimationState, CompositorEvent, MouseButton, MouseEventType, MozBrowserEvent}; +use script_traits::{AnimationState, CompositorEvent, DocumentActivity}; +use script_traits::{MouseButton, MouseEventType, MozBrowserEvent}; use script_traits::{ScriptMsg as ConstellationMsg, TouchpadPressurePhase}; use script_traits::{TouchEventType, TouchId}; use script_traits::UntrustedNodeAddress; @@ -191,7 +192,7 @@ pub struct Document { last_modified: Option<String>, encoding: Cell<EncodingRef>, is_html_document: bool, - is_fully_active: Cell<bool>, + activity: Cell<DocumentActivity>, url: DOMRefCell<ServoUrl>, quirks_mode: Cell<QuirksMode>, /// Caches for the getElement methods @@ -387,17 +388,33 @@ impl Document { self.trigger_mozbrowser_event(MozBrowserEvent::SecurityChange(https_state)); } - // https://html.spec.whatwg.org/multipage/#fully-active pub fn is_fully_active(&self) -> bool { - self.is_fully_active.get() - } - - pub fn fully_activate(&self) { - self.is_fully_active.set(true) - } - - pub fn fully_deactivate(&self) { - self.is_fully_active.set(false) + self.activity.get() == DocumentActivity::FullyActive + } + + pub fn is_active(&self) -> bool { + self.activity.get() != DocumentActivity::Inactive + } + + pub fn set_activity(&self, activity: DocumentActivity) { + // This function should only be called on documents with a browsing context + assert!(self.browsing_context.is_some()); + // Set the document's activity level, reflow if necessary, and suspend or resume timers. + if activity != self.activity.get() { + self.activity.set(activity); + if activity == DocumentActivity::FullyActive { + self.title_changed(); + self.dirty_all_nodes(); + self.window().reflow( + ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::CachedPageNeededReflow + ); + self.window().resume(); + } else { + self.window().suspend(); + } + } } pub fn origin(&self) -> &Origin { @@ -1892,6 +1909,7 @@ impl Document { is_html_document: IsHTMLDocument, content_type: Option<DOMString>, last_modified: Option<String>, + activity: DocumentActivity, source: DocumentSource, doc_loader: DocumentLoader, referrer: Option<String>, @@ -1927,7 +1945,7 @@ impl Document { // https://dom.spec.whatwg.org/#concept-document-encoding encoding: Cell::new(UTF_8), is_html_document: is_html_document == IsHTMLDocument::HTMLDocument, - is_fully_active: Cell::new(false), + activity: Cell::new(activity), id_map: DOMRefCell::new(HashMap::new()), tag_map: DOMRefCell::new(HashMap::new()), tagns_map: DOMRefCell::new(HashMap::new()), @@ -1995,6 +2013,7 @@ impl Document { IsHTMLDocument::NonHTMLDocument, None, None, + DocumentActivity::Inactive, DocumentSource::NotFromParser, docloader, None, @@ -2008,6 +2027,7 @@ impl Document { doctype: IsHTMLDocument, content_type: Option<DOMString>, last_modified: Option<String>, + activity: DocumentActivity, source: DocumentSource, doc_loader: DocumentLoader, referrer: Option<String>, @@ -2020,6 +2040,7 @@ impl Document { doctype, content_type, last_modified, + activity, source, doc_loader, referrer, @@ -2093,6 +2114,7 @@ impl Document { doctype, None, None, + DocumentActivity::Inactive, DocumentSource::NotFromParser, DocumentLoader::new(&self.loader()), None, diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs index 23521b94a09..45983c3292d 100644 --- a/components/script/dom/domimplementation.rs +++ b/components/script/dom/domimplementation.rs @@ -23,6 +23,7 @@ use dom::htmltitleelement::HTMLTitleElement; use dom::node::Node; use dom::text::Text; use dom::xmldocument::XMLDocument; +use script_traits::DocumentActivity; // https://dom.spec.whatwg.org/#domimplementation #[dom_struct] @@ -83,6 +84,7 @@ impl DOMImplementationMethods for DOMImplementation { IsHTMLDocument::NonHTMLDocument, Some(DOMString::from(content_type)), None, + DocumentActivity::Inactive, DocumentSource::NotFromParser, loader); // Step 2-3. @@ -129,6 +131,7 @@ impl DOMImplementationMethods for DOMImplementation { IsHTMLDocument::HTMLDocument, None, None, + DocumentActivity::Inactive, DocumentSource::NotFromParser, loader, None, diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs index c14bec8b594..54132ef94a9 100644 --- a/components/script/dom/domparser.rs +++ b/components/script/dom/domparser.rs @@ -19,6 +19,7 @@ use dom::document::{Document, IsHTMLDocument}; use dom::document::DocumentSource; use dom::servoparser::ServoParser; use dom::window::Window; +use script_traits::DocumentActivity; #[dom_struct] pub struct DOMParser { @@ -65,6 +66,7 @@ impl DOMParserMethods for DOMParser { IsHTMLDocument::HTMLDocument, Some(content_type), None, + DocumentActivity::Inactive, DocumentSource::FromParser, loader, None, @@ -82,6 +84,7 @@ impl DOMParserMethods for DOMParser { IsHTMLDocument::NonHTMLDocument, Some(content_type), None, + DocumentActivity::Inactive, DocumentSource::NotFromParser, loader, None, diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 71547c860bc..6931fca1822 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -65,6 +65,7 @@ use ref_slice::ref_slice; use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData, SVGSVGData}; use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddress}; use script_layout_interface::message::Msg; +use script_traits::DocumentActivity; use script_traits::UntrustedNodeAddress; use selectors::matching::{MatchingReason, matches}; use selectors::parser::SelectorList; @@ -1730,7 +1731,8 @@ impl Node { // https://github.com/whatwg/dom/issues/378 document.origin().alias(), is_html_doc, None, - None, DocumentSource::NotFromParser, loader, + None, DocumentActivity::Inactive, + DocumentSource::NotFromParser, loader, None, None); Root::upcast::<Node>(document) }, diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index aaa36a2098b..d64704b2368 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -35,6 +35,7 @@ use network_listener::PreInvoke; use profile_traits::time::{TimerMetadata, TimerMetadataFrameType}; use profile_traits::time::{TimerMetadataReflowType, ProfilerCategory, profile}; use script_thread::ScriptThread; +use script_traits::DocumentActivity; use servo_config::resource_files::read_resource_file; use servo_url::ServoUrl; use std::cell::Cell; @@ -107,6 +108,7 @@ impl ServoParser { IsHTMLDocument::HTMLDocument, None, None, + DocumentActivity::Inactive, DocumentSource::FromParser, loader, None, diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index cb9d5abdf07..37c62543526 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1488,21 +1488,17 @@ impl Window { None } - pub fn freeze(&self) { + pub fn suspend(&self) { self.upcast::<GlobalScope>().suspend(); // A hint to the JS runtime that now would be a good time to // GC any unreachable objects generated by user script, // or unattached DOM nodes. Attached DOM nodes can't be GCd yet, - // as the document might be thawed later. + // as the document might be reactivated later. self.Gc(); } - pub fn thaw(&self) { + pub fn resume(&self) { self.upcast::<GlobalScope>().resume(); - - // Push the document title to the compositor since we are - // activating this document due to a navigation. - self.Document().title_changed(); } pub fn need_emit_timeline_marker(&self, timeline_type: TimelineMarkerType) -> bool { diff --git a/components/script/dom/xmldocument.rs b/components/script/dom/xmldocument.rs index 87c639742f6..593749c4499 100644 --- a/components/script/dom/xmldocument.rs +++ b/components/script/dom/xmldocument.rs @@ -17,6 +17,7 @@ use dom::node::Node; use dom::window::Window; use js::jsapi::{JSContext, JSObject}; use origin::Origin; +use script_traits::DocumentActivity; use servo_url::ServoUrl; // https://dom.spec.whatwg.org/#xmldocument @@ -33,6 +34,7 @@ impl XMLDocument { is_html_document: IsHTMLDocument, content_type: Option<DOMString>, last_modified: Option<String>, + activity: DocumentActivity, source: DocumentSource, doc_loader: DocumentLoader) -> XMLDocument { XMLDocument { @@ -43,6 +45,7 @@ impl XMLDocument { is_html_document, content_type, last_modified, + activity, source, doc_loader, None, @@ -57,6 +60,7 @@ impl XMLDocument { doctype: IsHTMLDocument, content_type: Option<DOMString>, last_modified: Option<String>, + activity: DocumentActivity, source: DocumentSource, doc_loader: DocumentLoader) -> Root<XMLDocument> { @@ -68,6 +72,7 @@ impl XMLDocument { doctype, content_type, last_modified, + activity, source, doc_loader), window, diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 95a8ba0c3ad..f42afe87f8b 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -58,6 +58,7 @@ use net_traits::CoreResourceMsg::Fetch; use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode}; use net_traits::trim_http_whitespace; use network_listener::{NetworkListener, PreInvoke}; +use script_traits::DocumentActivity; use servo_atoms::Atom; use servo_config::prefs::PREFS; use servo_url::ServoUrl; @@ -1228,6 +1229,7 @@ impl XMLHttpRequest { is_html_document, content_type, None, + DocumentActivity::Inactive, DocumentSource::FromParser, docloader, None, diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 9bab1679aa6..44fc267b2bd 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -83,7 +83,8 @@ use profile_traits::time::{self, ProfilerCategory, profile}; use script_layout_interface::message::{self, NewLayoutThreadInfo, ReflowQueryType}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory, EnqueuedPromiseCallback}; use script_runtime::{ScriptPort, StackRootTLS, get_reports, new_rt_and_cx, PromiseJobQueue}; -use script_traits::{CompositorEvent, ConstellationControlMsg, DiscardBrowsingContext, EventResult}; +use script_traits::{CompositorEvent, ConstellationControlMsg}; +use script_traits::{DocumentActivity, DiscardBrowsingContext, EventResult}; use script_traits::{InitialScriptState, LayoutMsg, LoadData, MouseButton, MouseEventType, MozBrowserEvent}; use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg}; use script_traits::{ScriptThreadFactory, TimerEvent, TimerEventRequest, TimerSource}; @@ -148,8 +149,8 @@ struct InProgressLoad { window_size: Option<WindowSizeData>, /// Channel to the layout thread associated with this pipeline. layout_chan: Sender<message::Msg>, - /// Window is frozen (navigated away while loading for example). - is_frozen: bool, + /// The activity level of the document (inactive, active or fully active). + activity: DocumentActivity, /// Window is visible. is_visible: bool, /// The requested URL of the load. @@ -172,7 +173,7 @@ impl InProgressLoad { parent_info: parent_info, layout_chan: layout_chan, window_size: window_size, - is_frozen: false, + activity: DocumentActivity::FullyActive, is_visible: true, url: url, origin: origin, @@ -963,10 +964,8 @@ impl ScriptThread { self.handle_resize_inactive_msg(id, new_size), ConstellationControlMsg::GetTitle(pipeline_id) => self.handle_get_title_msg(pipeline_id), - ConstellationControlMsg::Freeze(pipeline_id) => - self.handle_freeze_msg(pipeline_id), - ConstellationControlMsg::Thaw(pipeline_id) => - self.handle_thaw_msg(pipeline_id), + ConstellationControlMsg::SetDocumentActivity(pipeline_id, activity) => + self.handle_set_document_activity_msg(pipeline_id, activity), ConstellationControlMsg::ChangeFrameVisibilityStatus(pipeline_id, visible) => self.handle_visibility_change_msg(pipeline_id, visible), ConstellationControlMsg::NotifyVisibilityChange(parent_pipeline_id, frame_id, visible) => @@ -1303,37 +1302,19 @@ impl ScriptThread { warn!("change visibility message sent to nonexistent pipeline"); } - /// Handles freeze message - fn handle_freeze_msg(&self, id: PipelineId) { + /// Handles activity change message + fn handle_set_document_activity_msg(&self, id: PipelineId, activity: DocumentActivity) { let document = self.documents.borrow().find_document(id); if let Some(document) = document { - document.window().freeze(); - document.fully_deactivate(); + document.set_activity(activity); return; } let mut loads = self.incomplete_loads.borrow_mut(); if let Some(ref mut load) = loads.iter_mut().find(|load| load.pipeline_id == id) { - load.is_frozen = true; + load.activity = activity; return; } - warn!("freeze sent to nonexistent pipeline"); - } - - /// Handles thaw message - fn handle_thaw_msg(&self, id: PipelineId) { - let document = self.documents.borrow().find_document(id); - if let Some(document) = document { - self.rebuild_and_force_reflow(&document, ReflowReason::CachedPageNeededReflow); - document.window().thaw(); - document.fully_activate(); - return; - } - let mut loads = self.incomplete_loads.borrow_mut(); - if let Some(ref mut load) = loads.iter_mut().find(|load| load.pipeline_id == id) { - load.is_frozen = false; - return; - } - warn!("thaw sent to nonexistent pipeline"); + warn!("change of activity sent to nonexistent pipeline"); } fn handle_focus_iframe_msg(&self, @@ -1759,16 +1740,13 @@ impl ScriptThread { is_html_document, content_type, last_modified, + incomplete.activity, DocumentSource::FromParser, loader, referrer, referrer_policy); document.set_ready_state(DocumentReadyState::Loading); - if !incomplete.is_frozen { - document.fully_activate(); - } - self.documents.borrow_mut().insert(incomplete.pipeline_id, &*document); window.init_document(&document); @@ -1822,8 +1800,8 @@ impl ScriptThread { ServoParser::parse_html_document(&document, parse_input, final_url); } - if incomplete.is_frozen { - window.upcast::<GlobalScope>().suspend(); + if incomplete.activity != DocumentActivity::FullyActive { + window.suspend(); } if !incomplete.is_visible { diff --git a/components/script/timers.rs b/components/script/timers.rs index 881fe9b6034..c1f0a1de6c4 100644 --- a/components/script/timers.rs +++ b/components/script/timers.rs @@ -233,6 +233,7 @@ impl OneshotTimers { return warn!("Suspending an already suspended timer."); } + debug!("Suspending timers."); self.suspended_since.set(Some(precise_time_ms())); self.invalidate_expected_event_id(); } @@ -244,6 +245,7 @@ impl OneshotTimers { None => return warn!("Resuming an already resumed timer."), }; + debug!("Resuming timers."); self.suspension_offset.set(self.suspension_offset.get() + additional_offset); self.suspended_since.set(None); @@ -252,7 +254,7 @@ impl OneshotTimers { fn schedule_timer_call(&self) { if self.suspended_since.get().is_some() { - // The timer will be scheduled when the pipeline is thawed. + // The timer will be scheduled when the pipeline is fully activated. return; } |