diff --git a/src/servo/html/cssparse.rs b/src/servo/html/cssparse.rs index 9273e8e2883..5856fc5ea83 100644 --- a/src/servo/html/cssparse.rs +++ b/src/servo/html/cssparse.rs @@ -2,28 +2,53 @@ Some little helpers for hooking up the HTML parser with the CSS parser */ -use std::net::url::Url; -use std::cell::Cell; use resource::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done}; + +use core::str; use newcss::stylesheet::Stylesheet; use newcss::util::DataStream; +use std::cell::Cell; +use std::net::url::Url; +use std::net::url; -pub fn spawn_css_parser(url: Url, resource_task: ResourceTask) -> comm::Port { +/// Where a style sheet comes from. +enum StylesheetProvenance { + UrlProvenance(Url), + InlineProvenance(Url, ~str), +} + +pub fn spawn_css_parser(provenance: StylesheetProvenance, + resource_task: ResourceTask) -> comm::Port { let result_port = comm::Port(); let result_chan = comm::Chan(&result_port); - do task::spawn |move url, copy resource_task| { - - let sheet = Stylesheet::new(copy url, data_stream(copy url, resource_task)); + + let provenance_cell = Cell(move provenance); + do task::spawn |move provenance_cell, copy resource_task| { + let url = do provenance_cell.with_ref |p| { + match *p { + UrlProvenance(copy the_url) => move the_url, + InlineProvenance(copy the_url, _) => move the_url + } + }; + + let sheet = Stylesheet::new(move url, data_stream(provenance_cell.take(), resource_task)); result_chan.send(move sheet); } return result_port; } -fn data_stream(url: Url, resource_task: ResourceTask) -> DataStream { - let input_port = Port(); - resource_task.send(Load(move url, input_port.chan())); - resource_port_to_data_stream(input_port) +fn data_stream(provenance: StylesheetProvenance, resource_task: ResourceTask) -> DataStream { + match move provenance { + UrlProvenance(move url) => { + let input_port = Port(); + resource_task.send(Load(move url, input_port.chan())); + resource_port_to_data_stream(input_port) + } + InlineProvenance(_, move data) => { + data_to_data_stream(move data) + } + } } fn resource_port_to_data_stream(input_port: comm::Port) -> DataStream { @@ -34,3 +59,16 @@ fn resource_port_to_data_stream(input_port: comm::Port) -> DataStre } } } + +fn data_to_data_stream(data: ~str) -> DataStream { + let data_cell = Cell(move data); + return |move data_cell| { + if data_cell.is_empty() { + None + } else { + // FIXME: Blech, a copy. + Some(str::to_bytes(data_cell.take())) + } + } +} + diff --git a/src/servo/html/hubbub_html_parser.rs b/src/servo/html/hubbub_html_parser.rs index 5fea36f40db..59d16d4897f 100644 --- a/src/servo/html/hubbub_html_parser.rs +++ b/src/servo/html/hubbub_html_parser.rs @@ -1,25 +1,24 @@ use au = gfx::geometry; use content::content_task::ContentTask; -use newcss::stylesheet::Stylesheet; use dom::cow; use dom::element::*; use dom::event::{Event, ReflowEvent}; -use dom::node::{Comment, Doctype, DoctypeData, Text, - Element, Node, NodeScope}; +use dom::node::{Comment, Doctype, DoctypeData, Element, Node, NodeScope, Text}; use resource::image_cache_task::ImageCacheTask; use resource::image_cache_task; use resource::resource_task::{Done, Load, Payload, ResourceTask}; +use core::comm::{Chan, Port}; +use cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser}; use hubbub::Attribute; - -use comm::{Chan, Port}; +use newcss::stylesheet::Stylesheet; use std::net::url::Url; -use cssparse::spawn_css_parser; +use std::net::url; type JSResult = ~[~[u8]]; enum CSSMessage { - CSSTaskNewFile(Url), + CSSTaskNewFile(StylesheetProvenance), CSSTaskExit } @@ -49,14 +48,15 @@ spawned, collates them, and sends them to the given result channel. * `from_parent` - A port on which to receive new links. */ -fn css_link_listener(to_parent : comm::Chan>, from_parent : comm::Port, +fn css_link_listener(to_parent : comm::Chan>, + from_parent : comm::Port, resource_task: ResourceTask) { let mut result_vec = ~[]; loop { match from_parent.recv() { - CSSTaskNewFile(move url) => { - result_vec.push(spawn_css_parser(move url, copy resource_task)); + CSSTaskNewFile(move provenance) => { + result_vec.push(spawn_css_parser(move provenance, copy resource_task)); } CSSTaskExit => { break; @@ -184,6 +184,31 @@ pub fn parse_html(scope: NodeScope, debug!("created parser"); parser.set_document_node(cast::transmute(cow::unwrap(root))); parser.enable_scripting(true); + + // Performs various actions necessary after appending has taken place. Currently, this consists + // of processing inline stylesheets, but in the future it might perform prefetching, etc. + let append_hook: @fn(Node, Node) = |parent_node, child_node| { + do scope.read(&parent_node) |parent_node_contents| { + do scope.read(&child_node) |child_node_contents| { + match (parent_node_contents.kind, child_node_contents.kind) { + (~Element(ref element), ~Text(ref data)) => { + match element.kind { + ~HTMLStyleElement => { + debug!("found inline CSS stylesheet"); + let url = url::from_str("http://example.com/"); // FIXME + let provenance = InlineProvenance(result::unwrap(move url), + copy *data); + css_chan.send(CSSTaskNewFile(provenance)); + } + _ => {} // Nothing to do. + } + } + _ => {} // Nothing to do. + } + } + } + }; + parser.set_tree_handler(@hubbub::TreeHandler { create_comment: |data: ~str| { debug!("create comment"); @@ -227,8 +252,8 @@ pub fn parse_html(scope: NodeScope, (Some(move rel), Some(move href)) => { if rel == ~"stylesheet" { debug!("found CSS stylesheet: %s", href); - css_chan.send(CSSTaskNewFile(make_url(move href, - Some(copy *url)))); + css_chan.send(CSSTaskNewFile(UrlProvenance(make_url(move href, + Some(copy *url))))); } } _ => {} @@ -262,6 +287,7 @@ pub fn parse_html(scope: NodeScope, let p: Node = cow::wrap(cast::transmute(parent)); let c: Node = cow::wrap(cast::transmute(child)); scope.add_child(p, c); + append_hook(p, c); } child },