tor-browser

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

stylesheet_loader.rs (5851B)


      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 use cssparser::SourceLocation;
      6 use nsstring::nsCString;
      7 use servo_arc::Arc;
      8 use style::context::QuirksMode;
      9 use style::gecko::data::GeckoStyleSheet;
     10 use style::gecko_bindings::bindings;
     11 use style::gecko_bindings::bindings::Gecko_LoadStyleSheet;
     12 use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
     13 use style::gecko_bindings::structs::{
     14    SheetLoadData, SheetLoadDataHolder, StyleSheet as DomStyleSheet,
     15 };
     16 use style::gecko_bindings::sugar::refptr::RefPtr;
     17 use style::global_style_data::GLOBAL_STYLE_DATA;
     18 use style::media_queries::MediaList;
     19 use style::shared_lock::{Locked, SharedRwLock};
     20 use style::stylesheets::import_rule::{ImportLayer, ImportSheet, ImportSupportsCondition};
     21 use style::stylesheets::AllowImportRules;
     22 use style::stylesheets::{ImportRule, Origin, StylesheetLoader as StyleStylesheetLoader};
     23 use style::stylesheets::{StylesheetContents, UrlExtraData};
     24 use style::values::CssUrl;
     25 
     26 pub struct StylesheetLoader(
     27    *mut Loader,
     28    *mut DomStyleSheet,
     29    *mut SheetLoadData,
     30    *mut LoaderReusableStyleSheets,
     31 );
     32 
     33 impl StylesheetLoader {
     34    pub fn new(
     35        loader: *mut Loader,
     36        parent: *mut DomStyleSheet,
     37        parent_load_data: *mut SheetLoadData,
     38        reusable_sheets: *mut LoaderReusableStyleSheets,
     39    ) -> Self {
     40        StylesheetLoader(loader, parent, parent_load_data, reusable_sheets)
     41    }
     42 }
     43 
     44 impl StyleStylesheetLoader for StylesheetLoader {
     45    fn request_stylesheet(
     46        &self,
     47        url: CssUrl,
     48        source_location: SourceLocation,
     49        lock: &SharedRwLock,
     50        media: Arc<Locked<MediaList>>,
     51        supports: Option<ImportSupportsCondition>,
     52        layer: ImportLayer,
     53    ) -> Arc<Locked<ImportRule>> {
     54        // Ensure the supports conditions for this @import are true, if not, refuse to load
     55        if !supports.as_ref().map_or(true, |s| s.enabled) {
     56            return Arc::new(lock.wrap(ImportRule {
     57                url,
     58                stylesheet: ImportSheet::new_refused(),
     59                supports,
     60                layer,
     61                source_location,
     62            }));
     63        }
     64 
     65        // After we get this raw pointer ImportRule will be moved into a lock and Arc
     66        // and so the Arc<Url> pointer inside will also move,
     67        // but the Url it points to or the allocating backing the String inside that Url won’t,
     68        // so this raw pointer will still be valid.
     69 
     70        let child_sheet =
     71            unsafe { Gecko_LoadStyleSheet(self.0, self.1, self.2, self.3, &url, media.into()) };
     72 
     73        debug_assert!(
     74            !child_sheet.is_null(),
     75            "Import rules should always have a strong sheet"
     76        );
     77        let sheet = unsafe { GeckoStyleSheet::from_addrefed(child_sheet) };
     78        let stylesheet = ImportSheet::new(sheet);
     79        Arc::new(lock.wrap(ImportRule {
     80            url,
     81            stylesheet,
     82            supports,
     83            layer,
     84            source_location,
     85        }))
     86    }
     87 }
     88 
     89 pub struct AsyncStylesheetParser {
     90    load_data: RefPtr<SheetLoadDataHolder>,
     91    extra_data: UrlExtraData,
     92    bytes: nsCString,
     93    origin: Origin,
     94    quirks_mode: QuirksMode,
     95    allow_import_rules: AllowImportRules,
     96 }
     97 
     98 impl AsyncStylesheetParser {
     99    pub fn new(
    100        load_data: RefPtr<SheetLoadDataHolder>,
    101        extra_data: UrlExtraData,
    102        bytes: nsCString,
    103        origin: Origin,
    104        quirks_mode: QuirksMode,
    105        allow_import_rules: AllowImportRules,
    106    ) -> Self {
    107        AsyncStylesheetParser {
    108            load_data,
    109            extra_data,
    110            bytes,
    111            origin,
    112            quirks_mode,
    113            allow_import_rules,
    114        }
    115    }
    116 
    117    pub fn parse(self) {
    118        let global_style_data = &*GLOBAL_STYLE_DATA;
    119        let input: &str = unsafe { (*self.bytes).as_str_unchecked() };
    120 
    121        // Note: Parallel CSS parsing doesn't report CSS errors. When errors are
    122        // being logged, Gecko prevents the parallel parsing path from running.
    123        let sheet = StylesheetContents::from_str(
    124            input,
    125            self.extra_data.clone(),
    126            self.origin,
    127            &global_style_data.shared_lock,
    128            Some(&self),
    129            None,
    130            self.quirks_mode.into(),
    131            self.allow_import_rules,
    132            /* sanitized_output = */ None,
    133        );
    134 
    135        unsafe {
    136            bindings::Gecko_StyleSheet_FinishAsyncParse(self.load_data.get(), sheet.into());
    137        }
    138    }
    139 }
    140 
    141 impl StyleStylesheetLoader for AsyncStylesheetParser {
    142    fn request_stylesheet(
    143        &self,
    144        url: CssUrl,
    145        source_location: SourceLocation,
    146        lock: &SharedRwLock,
    147        media: Arc<Locked<MediaList>>,
    148        supports: Option<ImportSupportsCondition>,
    149        layer: ImportLayer,
    150    ) -> Arc<Locked<ImportRule>> {
    151        // Ensure the supports conditions for this @import are true, if not, refuse to load
    152        if !supports.as_ref().map_or(true, |s| s.enabled) {
    153            return Arc::new(lock.wrap(ImportRule {
    154                url: url.clone(),
    155                stylesheet: ImportSheet::new_refused(),
    156                supports,
    157                layer,
    158                source_location,
    159            }));
    160        }
    161 
    162        let stylesheet = ImportSheet::new_pending();
    163        let rule = Arc::new(lock.wrap(ImportRule {
    164            url: url.clone(),
    165            stylesheet,
    166            supports,
    167            layer,
    168            source_location,
    169        }));
    170 
    171        unsafe {
    172            bindings::Gecko_LoadStyleSheetAsync(
    173                self.load_data.get(),
    174                &url,
    175                media.into(),
    176                rule.clone().into(),
    177            );
    178        }
    179 
    180        rule
    181    }
    182 }