tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

origin.rs (7020B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      4 
      5 //! [CSS cascade origins](https://drafts.csswg.org/css-cascade/#cascading-origins).
      6 
      7 use crate::derives::*;
      8 use std::marker::PhantomData;
      9 use std::ops::BitOrAssign;
     10 
     11 /// Each style rule has an origin, which determines where it enters the cascade.
     12 ///
     13 /// <https://drafts.csswg.org/css-cascade/#cascading-origins>
     14 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem, PartialOrd, Ord)]
     15 #[repr(u8)]
     16 pub enum Origin {
     17    /// <https://drafts.csswg.org/css-cascade/#cascade-origin-user-agent>
     18    UserAgent = 0x1,
     19 
     20    /// <https://drafts.csswg.org/css-cascade/#cascade-origin-user>
     21    User = 0x2,
     22 
     23    /// <https://drafts.csswg.org/css-cascade/#cascade-origin-author>
     24    Author = 0x4,
     25 }
     26 
     27 impl Origin {
     28    /// Returns an origin that goes in order for `index`.
     29    ///
     30    /// This is used for iterating across origins.
     31    fn from_index(index: i8) -> Option<Self> {
     32        Some(match index {
     33            0 => Origin::Author,
     34            1 => Origin::User,
     35            2 => Origin::UserAgent,
     36            _ => return None,
     37        })
     38    }
     39 
     40    fn to_index(self) -> i8 {
     41        match self {
     42            Origin::Author => 0,
     43            Origin::User => 1,
     44            Origin::UserAgent => 2,
     45        }
     46    }
     47 
     48    /// Returns an iterator from this origin, towards all the less specific
     49    /// origins. So for `UserAgent`, it'd iterate through all origins.
     50    #[inline]
     51    pub fn following_including(self) -> OriginSetIterator {
     52        OriginSetIterator {
     53            set: OriginSet::ORIGIN_USER | OriginSet::ORIGIN_AUTHOR | OriginSet::ORIGIN_USER_AGENT,
     54            cur: self.to_index(),
     55            rev: true,
     56        }
     57    }
     58 }
     59 
     60 /// A set of origins. This is equivalent to Gecko's OriginFlags.
     61 #[derive(Clone, Copy, PartialEq, MallocSizeOf)]
     62 pub struct OriginSet(u8);
     63 bitflags! {
     64    impl OriginSet: u8 {
     65        /// <https://drafts.csswg.org/css-cascade/#cascade-origin-user-agent>
     66        const ORIGIN_USER_AGENT = Origin::UserAgent as u8;
     67        /// <https://drafts.csswg.org/css-cascade/#cascade-origin-user>
     68        const ORIGIN_USER = Origin::User as u8;
     69        /// <https://drafts.csswg.org/css-cascade/#cascade-origin-author>
     70        const ORIGIN_AUTHOR = Origin::Author as u8;
     71    }
     72 }
     73 
     74 impl OriginSet {
     75    /// Returns an iterator over the origins present in this `OriginSet`.
     76    ///
     77    /// See the `OriginSet` documentation for information about the order
     78    /// origins are iterated.
     79    pub fn iter_origins(&self) -> OriginSetIterator {
     80        OriginSetIterator {
     81            set: *self,
     82            cur: 0,
     83            rev: false,
     84        }
     85    }
     86 }
     87 
     88 impl From<Origin> for OriginSet {
     89    fn from(origin: Origin) -> Self {
     90        Self::from_bits_retain(origin as u8)
     91    }
     92 }
     93 
     94 impl BitOrAssign<Origin> for OriginSet {
     95    fn bitor_assign(&mut self, origin: Origin) {
     96        *self |= OriginSet::from(origin);
     97    }
     98 }
     99 
    100 /// Iterates over the origins present in an `OriginSet`, in order from
    101 /// highest priority (author) to lower (user agent).
    102 #[derive(Clone)]
    103 pub struct OriginSetIterator {
    104    set: OriginSet,
    105    cur: i8,
    106    rev: bool,
    107 }
    108 
    109 impl Iterator for OriginSetIterator {
    110    type Item = Origin;
    111 
    112    fn next(&mut self) -> Option<Origin> {
    113        loop {
    114            let origin = Origin::from_index(self.cur)?;
    115 
    116            if self.rev {
    117                self.cur -= 1;
    118            } else {
    119                self.cur += 1;
    120            }
    121 
    122            if self.set.contains(origin.into()) {
    123                return Some(origin);
    124            }
    125        }
    126    }
    127 }
    128 
    129 /// An object that stores a `T` for each origin of the CSS cascade.
    130 #[derive(Debug, Default, MallocSizeOf)]
    131 pub struct PerOrigin<T> {
    132    /// Data for `Origin::UserAgent`.
    133    pub user_agent: T,
    134 
    135    /// Data for `Origin::User`.
    136    pub user: T,
    137 
    138    /// Data for `Origin::Author`.
    139    pub author: T,
    140 }
    141 
    142 impl<T> PerOrigin<T> {
    143    /// Returns a reference to the per-origin data for the specified origin.
    144    #[inline]
    145    pub fn borrow_for_origin(&self, origin: &Origin) -> &T {
    146        match *origin {
    147            Origin::UserAgent => &self.user_agent,
    148            Origin::User => &self.user,
    149            Origin::Author => &self.author,
    150        }
    151    }
    152 
    153    /// Returns a mutable reference to the per-origin data for the specified
    154    /// origin.
    155    #[inline]
    156    pub fn borrow_mut_for_origin(&mut self, origin: &Origin) -> &mut T {
    157        match *origin {
    158            Origin::UserAgent => &mut self.user_agent,
    159            Origin::User => &mut self.user,
    160            Origin::Author => &mut self.author,
    161        }
    162    }
    163 
    164    /// Iterates over references to per-origin extra style data, from highest
    165    /// level (author) to lowest (user agent).
    166    pub fn iter_origins(&self) -> PerOriginIter<'_, T> {
    167        PerOriginIter {
    168            data: &self,
    169            cur: 0,
    170            rev: false,
    171        }
    172    }
    173 
    174    /// Iterates over references to per-origin extra style data, from lowest
    175    /// level (user agent) to highest (author).
    176    pub fn iter_origins_rev(&self) -> PerOriginIter<'_, T> {
    177        PerOriginIter {
    178            data: &self,
    179            cur: 2,
    180            rev: true,
    181        }
    182    }
    183 
    184    /// Iterates over mutable references to per-origin extra style data, from
    185    /// highest level (author) to lowest (user agent).
    186    pub fn iter_mut_origins(&mut self) -> PerOriginIterMut<'_, T> {
    187        PerOriginIterMut {
    188            data: self,
    189            cur: 0,
    190            _marker: PhantomData,
    191        }
    192    }
    193 }
    194 
    195 /// Iterator over `PerOrigin<T>`, from highest level (author) to lowest
    196 /// (user agent).
    197 ///
    198 /// We rely on this specific order for correctly looking up @font-face,
    199 /// @counter-style and @keyframes rules.
    200 pub struct PerOriginIter<'a, T: 'a> {
    201    data: &'a PerOrigin<T>,
    202    cur: i8,
    203    rev: bool,
    204 }
    205 
    206 impl<'a, T> Iterator for PerOriginIter<'a, T>
    207 where
    208    T: 'a,
    209 {
    210    type Item = (&'a T, Origin);
    211 
    212    fn next(&mut self) -> Option<Self::Item> {
    213        let origin = Origin::from_index(self.cur)?;
    214 
    215        self.cur += if self.rev { -1 } else { 1 };
    216 
    217        Some((self.data.borrow_for_origin(&origin), origin))
    218    }
    219 }
    220 
    221 /// Like `PerOriginIter<T>`, but iterates over mutable references to the
    222 /// per-origin data.
    223 ///
    224 /// We must use unsafe code here since it's not possible for the borrow
    225 /// checker to know that we are safely returning a different reference
    226 /// each time from `next()`.
    227 pub struct PerOriginIterMut<'a, T: 'a> {
    228    data: *mut PerOrigin<T>,
    229    cur: i8,
    230    _marker: PhantomData<&'a mut PerOrigin<T>>,
    231 }
    232 
    233 impl<'a, T> Iterator for PerOriginIterMut<'a, T>
    234 where
    235    T: 'a,
    236 {
    237    type Item = (&'a mut T, Origin);
    238 
    239    fn next(&mut self) -> Option<Self::Item> {
    240        let origin = Origin::from_index(self.cur)?;
    241 
    242        self.cur += 1;
    243 
    244        Some((
    245            unsafe { (*self.data).borrow_mut_for_origin(&origin) },
    246            origin,
    247        ))
    248    }
    249 }