diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 20ef9ff6cb4..342f8195cb6 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -1542,6 +1542,7 @@ fn get_ua_stylesheets() -> Result { None, Origin::UserAgent, Default::default(), + None, Box::new(StdoutErrorReporter), ParserContextExtraData::default())) } @@ -1555,7 +1556,8 @@ fn get_ua_stylesheets() -> Result { for &(ref contents, ref url) in &opts::get().user_stylesheets { user_or_user_agent_stylesheets.push(Stylesheet::from_bytes( &contents, url.clone(), None, None, Origin::User, Default::default(), - Box::new(StdoutErrorReporter), ParserContextExtraData::default())); + None, Box::new(StdoutErrorReporter), + ParserContextExtraData::default())); } let quirks_mode_stylesheet = try!(parse_ua_stylesheet("quirks-mode.css")); diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 37dd578f3ad..1933d98e583 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -307,6 +307,7 @@ impl CssRule { let mut rule_parser = TopLevelRuleParser { stylesheet_origin: parent_stylesheet.origin, context: context, + loader: None, state: Cell::new(state), namespaces: &mut namespaces, }; @@ -605,9 +606,20 @@ rule_filter! { effective_keyframes_rules(Keyframes => KeyframesRule), } +/// The stylesheet loader is the abstraction used to trigger network requests +/// for `@import` rules. +pub trait StylesheetLoader { + /// Request a stylesheet after parsing a given `@import` rule. + /// + /// The called code is responsible to update the `stylesheet` rules field + /// when the sheet is done loading. + fn request_stylesheet(&self, import: &Arc>); +} + struct TopLevelRuleParser<'a> { stylesheet_origin: Origin, namespaces: &'a mut Namespaces, + loader: Option<&'a StylesheetLoader>, context: ParserContext<'a>, state: Cell, } @@ -679,6 +691,12 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> { } )); + if is_valid_url { + let loader = self.loader + .expect("Expected a stylesheet loader for @import"); + loader.request_stylesheet(&import_rule); + } + return Ok(AtRuleType::WithoutBlock(CssRule::Import(import_rule))) } else { self.state.set(State::Invalid); diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 394653afd8e..dcec9a5c1ac 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -60,6 +60,7 @@ use style::thread_state; use style::timer::Timer; use style::traversal::{recalc_style_at, DomTraversalContext, PerLevelTraversalData}; use style_traits::ToCss; +use stylesheet_loader::StylesheetLoader; /* * For Gecko->Servo function calls, we need to redeclare the same signature that was declared in @@ -232,8 +233,10 @@ pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyl SheetParsingMode::eUserSheetFeatures => Origin::User, SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent, }; + let loader = StylesheetLoader::new(); let sheet = Arc::new(Stylesheet::from_str( - "", url, origin, Default::default(), Box::new(StdoutErrorReporter), extra_data)); + "", url, origin, Default::default(), Some(&loader), + Box::new(StdoutErrorReporter), extra_data)); unsafe { transmute(sheet) } @@ -262,8 +265,10 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(data: *const nsACString, referrer: Some(GeckoArcURI::new(referrer)), principal: Some(GeckoArcPrincipal::new(principal)), }}; + let loader = StylesheetLoader::new(); let sheet = Arc::new(Stylesheet::from_str( - input, url, origin, Default::default(), Box::new(StdoutErrorReporter), extra_data)); + input, url, origin, Default::default(), Some(&loader), + Box::new(StdoutErrorReporter), extra_data)); unsafe { transmute(sheet) } diff --git a/ports/geckolib/lib.rs b/ports/geckolib/lib.rs index 0087e6aece6..1225045e45c 100644 --- a/ports/geckolib/lib.rs +++ b/ports/geckolib/lib.rs @@ -18,6 +18,7 @@ extern crate style_traits; #[allow(non_snake_case)] pub mod glue; +mod stylesheet_loader; // FIXME(bholley): This should probably go away once we harmonize the allocators. #[no_mangle] diff --git a/ports/geckolib/stylesheet_loader.rs b/ports/geckolib/stylesheet_loader.rs new file mode 100644 index 00000000000..9db89333747 --- /dev/null +++ b/ports/geckolib/stylesheet_loader.rs @@ -0,0 +1,21 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +use parking_lot::RwLock; +use std::sync::Arc; +use style::stylesheets::{ImportRule, StylesheetLoader as StyleStylesheetLoader}; + +pub struct StylesheetLoader; + +impl StylesheetLoader { + pub fn new() -> Self { + StylesheetLoader + } +} + +impl StyleStylesheetLoader for StylesheetLoader { + fn request_stylesheet(&self, _import: &Arc>) { + // FIXME(emilio): Implement `@import` in stylo. + } +} diff --git a/tests/unit/style/media_queries.rs b/tests/unit/style/media_queries.rs index 8c91a5b52bb..ac5a9b501c2 100644 --- a/tests/unit/style/media_queries.rs +++ b/tests/unit/style/media_queries.rs @@ -29,7 +29,8 @@ fn test_media_rule(css: &str, callback: F) where F: Fn(&MediaList, &str) { let url = ServoUrl::parse("http://localhost").unwrap(); let stylesheet = Stylesheet::from_str( css, url, Origin::Author, Default::default(), - Box::new(CSSErrorReporterTest), ParserContextExtraData::default()); + None, Box::new(CSSErrorReporterTest), + ParserContextExtraData::default()); let mut rule_count = 0; media_queries(&stylesheet.rules.read().0, &mut |mq| { rule_count += 1; @@ -53,7 +54,8 @@ fn media_query_test(device: &Device, css: &str, expected_rule_count: usize) { let url = ServoUrl::parse("http://localhost").unwrap(); let ss = Stylesheet::from_str( css, url, Origin::Author, Default::default(), - Box::new(CSSErrorReporterTest), ParserContextExtraData::default()); + None, Box::new(CSSErrorReporterTest), + ParserContextExtraData::default()); let mut rule_count = 0; ss.effective_style_rules(device, |_| rule_count += 1); assert!(rule_count == expected_rule_count, css.to_owned()); diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index d4c8bcc28a1..40ad06d8e4f 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -52,6 +52,7 @@ fn test_parse_stylesheet() { }"; let url = ServoUrl::parse("about::test").unwrap(); let stylesheet = Stylesheet::from_str(css, url.clone(), Origin::UserAgent, Default::default(), + None, Box::new(CSSErrorReporterTest), ParserContextExtraData::default()); let mut namespaces = Namespaces::default(); @@ -332,7 +333,9 @@ fn test_report_error_stylesheet() { let errors = error_reporter.errors.clone(); - Stylesheet::from_str(css, url, Origin::UserAgent, Default::default(), error_reporter, + Stylesheet::from_str(css, url, Origin::UserAgent, Default::default(), + None, + error_reporter, ParserContextExtraData::default()); let mut errors = errors.lock().unwrap(); diff --git a/tests/unit/style/viewport.rs b/tests/unit/style/viewport.rs index 9a3bc773a9c..2ca9733afc2 100644 --- a/tests/unit/style/viewport.rs +++ b/tests/unit/style/viewport.rs @@ -25,6 +25,7 @@ macro_rules! stylesheet { ServoUrl::parse("http://localhost").unwrap(), Origin::$origin, Default::default(), + None, $error_reporter, ParserContextExtraData::default() )) diff --git a/tests/unit/stylo/lib.rs b/tests/unit/stylo/lib.rs index d28f0663d0e..35fcdd01602 100644 --- a/tests/unit/stylo/lib.rs +++ b/tests/unit/stylo/lib.rs @@ -16,5 +16,8 @@ extern crate style_traits; mod sanity_checks; +#[path = "../../../ports/geckolib/stylesheet_loader.rs"] +mod stylesheet_loader; + mod servo_function_signatures;