From 87b1e1cdc9b380687564ddf0dc894a10e5df7221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 14 Aug 2018 10:47:25 +0200 Subject: [PATCH] style: no-op visited changes earlier if visited links are disabled. We force a repaint from ContentStateChangedInternal if visited links are disabled, and that's observable. Let's cut it off as early as we can to avoid timing attacks even when :visited is disabled. Differential Revision: https://phabricator.services.mozilla.com/D3304 --- components/style/gecko/data.rs | 48 ++++--------------- .../element/state_and_attributes.rs | 7 ++- 2 files changed, 14 insertions(+), 41 deletions(-) diff --git a/components/style/gecko/data.rs b/components/style/gecko/data.rs index 6b9005c7560..0bd938c67e8 100644 --- a/components/style/gecko/data.rs +++ b/components/style/gecko/data.rs @@ -8,7 +8,7 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use context::QuirksMode; use dom::TElement; use gecko_bindings::bindings::{self, RawServoStyleSet}; -use gecko_bindings::structs::{self, RawGeckoPresContextOwned, ServoStyleSetSizes, StyleSheet as DomStyleSheet}; +use gecko_bindings::structs::{RawGeckoPresContextOwned, ServoStyleSetSizes, StyleSheet as DomStyleSheet}; use gecko_bindings::structs::{StyleSheetInfo, nsIDocument}; use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI}; use invalidation::media_queries::{MediaListKey, ToMediaListKey}; @@ -185,52 +185,20 @@ impl PerDocumentStyleDataImpl { .flush(&StylesheetGuards::same(guard), document_element, snapshots) } - /// Returns whether private browsing is enabled. - fn is_private_browsing_enabled(&self) -> bool { - let doc = self.stylist - .device() - .pres_context() - .mDocument - .raw::(); - unsafe { bindings::Gecko_IsPrivateBrowsingEnabled(doc) } - } - - /// Returns whether the document is being used as an image. - fn is_being_used_as_an_image(&self) -> bool { - let doc = self.stylist - .device() - .pres_context() - .mDocument - .raw::(); - - unsafe { (*doc).mIsBeingUsedAsImage() } - } - /// Get the default computed values for this document. pub fn default_computed_values(&self) -> &Arc { self.stylist.device().default_computed_values_arc() } - /// Returns whether visited links are enabled. - fn visited_links_enabled(&self) -> bool { - unsafe { structs::StaticPrefs_sVarCache_layout_css_visited_links_enabled } - } - /// Returns whether visited styles are enabled. + #[inline] pub fn visited_styles_enabled(&self) -> bool { - if !self.visited_links_enabled() { - return false; - } - - if self.is_private_browsing_enabled() { - return false; - } - - if self.is_being_used_as_an_image() { - return false; - } - - true + let doc = self.stylist + .device() + .pres_context() + .mDocument + .raw::(); + unsafe { bindings::Gecko_VisitedStylesEnabled(doc) } } /// Measure heap usage. diff --git a/components/style/invalidation/element/state_and_attributes.rs b/components/style/invalidation/element/state_and_attributes.rs index 88b012a2524..0be44c1fc42 100644 --- a/components/style/invalidation/element/state_and_attributes.rs +++ b/components/style/invalidation/element/state_and_attributes.rs @@ -167,8 +167,13 @@ where // do for this case. if state_changes.intersects(ElementState::IN_VISITED_OR_UNVISITED_STATE) { trace!(" > visitedness change, force subtree restyle"); + // If we get here with visited links disabled, we should probably + // just avoid the restyle and remove the state change here, not only + // as an optimization, but also because it kind of would kill the + // point of disabling visited links. + debug_assert!(self.shared_context.visited_styles_enabled); // We can't just return here because there may also be attribute - // changes as well that imply additional hints. + // changes as well that imply additional hints for siblings. self.data.hint.insert(RestyleHint::restyle_subtree()); }