1use crate::parser::{Parse, ParserContext};
8use crate::stylesheets::CorsMode;
9use cssparser::{Parser, SourceLocation};
10use style_traits::ParseError;
11
12#[cfg(feature = "gecko")]
13pub mod gecko;
14#[cfg(feature = "gecko")]
15pub use gecko::{ComputedUrl, CssUrl, SpecifiedUrl};
16#[cfg(feature = "servo")]
17pub mod servo;
18#[cfg(feature = "servo")]
19pub use servo::{ComputedUrl, CssUrl, SpecifiedUrl};
20
21impl CssUrl {
22 pub fn parse_with_cors_mode<'i, 't>(
24 context: &ParserContext,
25 input: &mut Parser<'i, 't>,
26 cors_mode: CorsMode,
27 ) -> Result<Self, ParseError<'i>> {
28 let start = input.position().byte_index();
29 let location = input.current_source_location();
30 let url = input.expect_url()?;
31 let end = input.position().byte_index();
32 Self::parse_from_string(
33 url.as_ref().to_owned(),
34 start,
35 end,
36 context,
37 cors_mode,
38 location,
39 )
40 }
41
42 pub fn parse_from_string<'i>(
46 url: String,
47 url_start: usize,
48 url_end: usize,
49 context: &ParserContext,
50 cors_mode: CorsMode,
51 location: SourceLocation,
52 ) -> Result<Self, ParseError<'i>> {
53 use crate::custom_properties::AttrTaintedRange;
54 use style_traits::StyleParseErrorKind;
55 let range = AttrTaintedRange::new(url_start, url_end);
56 if context.disallow_urls_in_range(&range) {
57 return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
58 }
59 Ok(Self::new_from_string(url, context, cors_mode))
60 }
61
62 pub fn new_from_untainted_string(
67 url: String,
68 context: &ParserContext,
69 cors_mode: CorsMode,
70 ) -> Self {
71 debug_assert!(context.attr_tainted_regions.is_empty());
72 Self::new_from_string(url, context, cors_mode)
73 }
74}
75
76impl Parse for CssUrl {
77 fn parse<'i, 't>(
78 context: &ParserContext,
79 input: &mut Parser<'i, 't>,
80 ) -> Result<Self, ParseError<'i>> {
81 Self::parse_with_cors_mode(context, input, CorsMode::None)
82 }
83}