Allow image prefetching to occur during parsing when no window or document is present. Fixes #939.

This commit is contained in:
Josh Matthews 2013-09-13 23:10:31 -07:00
parent 34f740396e
commit 21b0fc35b6
4 changed files with 47 additions and 35 deletions

View file

@ -166,11 +166,19 @@ impl<'self> Element {
//XXXjdm We really need something like a vtable so we can call AfterSetAttr. //XXXjdm We really need something like a vtable so we can call AfterSetAttr.
// This hardcoding is awful. // This hardcoding is awful.
if abstract_self.is_iframe_element() { match abstract_self.type_id() {
ElementNodeTypeId(HTMLImageElementTypeId) => {
do abstract_self.with_mut_image_element |image| {
image.AfterSetAttr(raw_name, raw_value);
}
}
ElementNodeTypeId(HTMLIframeElementTypeId) => {
do abstract_self.with_mut_iframe_element |iframe| { do abstract_self.with_mut_iframe_element |iframe| {
iframe.AfterSetAttr(raw_name, raw_value); iframe.AfterSetAttr(raw_name, raw_value);
} }
} }
_ => ()
}
match self.parent.owner_doc { match self.parent.owner_doc {
Some(owner) => do owner.with_base |owner| { owner.content_changed() }, Some(owner) => do owner.with_base |owner| { owner.content_changed() },

View file

@ -9,6 +9,7 @@ use extra::url::Url;
use gfx::geometry::to_px; use gfx::geometry::to_px;
use layout_interface::{ContentBoxQuery, ContentBoxResponse}; use layout_interface::{ContentBoxQuery, ContentBoxResponse};
use servo_net::image_cache_task; use servo_net::image_cache_task;
use servo_net::image_cache_task::ImageCacheTask;
use servo_util::url::make_url; use servo_util::url::make_url;
pub struct HTMLImageElement { pub struct HTMLImageElement {
@ -19,21 +20,13 @@ pub struct HTMLImageElement {
impl HTMLImageElement { impl HTMLImageElement {
/// Makes the local `image` member match the status of the `src` attribute and starts /// Makes the local `image` member match the status of the `src` attribute and starts
/// prefetching the image. This method must be called after `src` is changed. /// prefetching the image. This method must be called after `src` is changed.
pub fn update_image(&mut self) { pub fn update_image(&mut self, image_cache: ImageCacheTask, url: Option<Url>) {
let elem = &mut self.parent.parent; let elem = &mut self.parent.parent;
let src_opt = elem.get_attr("src").map(|x| x.to_str()); let src_opt = elem.get_attr("src").map(|x| x.to_str());
let node = &mut elem.parent;
match node.owner_doc {
Some(doc) => {
match doc.with_base(|doc| doc.window) {
Some(window) => {
match src_opt { match src_opt {
None => {} None => {}
Some(src) => { Some(src) => {
let page = window.page; let img_url = make_url(src, url);
let img_url = make_url(src,
(*page).url
.map(|&(ref url, _)| url.clone()));
self.image = Some(img_url.clone()); self.image = Some(img_url.clone());
// inform the image cache to load this, but don't store a // inform the image cache to load this, but don't store a
@ -41,14 +34,23 @@ impl HTMLImageElement {
// //
// TODO (Issue #84): don't prefetch if we are within a // TODO (Issue #84): don't prefetch if we are within a
// <noscript> tag. // <noscript> tag.
window.image_cache_task.send(image_cache_task::Prefetch(img_url)); image_cache.send(image_cache_task::Prefetch(img_url));
} }
} }
} }
None => {}
pub fn AfterSetAttr(&mut self, name: &DOMString, _value: &DOMString) {
let name = name.to_str();
if "src" == name {
let doc = self.parent.parent.parent.owner_doc;
for doc in doc.iter() {
do doc.with_base |doc| {
for window in doc.window.iter() {
let url = window.page.url.map(|&(ref url, _)| url.clone());
self.update_image(window.image_cache_task.clone(), url);
}
} }
} }
None => {}
} }
} }
@ -67,14 +69,11 @@ impl HTMLImageElement {
abstract_self: AbstractNode<ScriptView>, abstract_self: AbstractNode<ScriptView>,
src: &DOMString, src: &DOMString,
_rv: &mut ErrorResult) { _rv: &mut ErrorResult) {
{
let node = &mut self.parent.parent; let node = &mut self.parent.parent;
node.set_attr(abstract_self, node.set_attr(abstract_self,
&str(~"src"), &str(~"src"),
&str(src.to_str())); &str(src.to_str()));
} }
self.update_image();
}
pub fn CrossOrigin(&self) -> DOMString { pub fn CrossOrigin(&self) -> DOMString {
null_string null_string

View file

@ -24,6 +24,7 @@ use std::task;
use std::from_str::FromStr; use std::from_str::FromStr;
use hubbub::hubbub; use hubbub::hubbub;
use servo_msg::constellation_msg::{ConstellationChan, SubpageId}; use servo_msg::constellation_msg::{ConstellationChan, SubpageId};
use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::{Done, Load, Payload, ResourceTask}; use servo_net::resource_task::{Done, Load, Payload, ResourceTask};
use servo_util::tree::TreeNodeRef; use servo_util::tree::TreeNodeRef;
use servo_util::url::make_url; use servo_util::url::make_url;
@ -300,6 +301,7 @@ pub fn build_element_from_tag(cx: *JSContext, tag: &str) -> AbstractNode<ScriptV
pub fn parse_html(cx: *JSContext, pub fn parse_html(cx: *JSContext,
url: Url, url: Url,
resource_task: ResourceTask, resource_task: ResourceTask,
image_cache_task: ImageCacheTask,
next_subpage_id: SubpageId, next_subpage_id: SubpageId,
constellation_chan: ConstellationChan) -> HtmlParserResult { constellation_chan: ConstellationChan) -> HtmlParserResult {
debug!("Hubbub: parsing %?", url); debug!("Hubbub: parsing %?", url);
@ -431,9 +433,11 @@ pub fn parse_html(cx: *JSContext,
} }
} }
//FIXME: This should be taken care of by set_attr, but we don't have
// access to a window so HTMLImageElement::AfterSetAttr bails.
ElementNodeTypeId(HTMLImageElementTypeId) => { ElementNodeTypeId(HTMLImageElementTypeId) => {
do node.with_mut_image_element |image_element| { do node.with_mut_image_element |image_element| {
image_element.update_image(); image_element.update_image(image_cache_task.clone(), Some(url2.clone()));
} }
} }

View file

@ -649,6 +649,7 @@ impl ScriptTask {
let html_parsing_result = hubbub_html_parser::parse_html(cx.ptr, let html_parsing_result = hubbub_html_parser::parse_html(cx.ptr,
url.clone(), url.clone(),
self.resource_task.clone(), self.resource_task.clone(),
self.image_cache_task.clone(),
page.next_subpage_id.clone(), page.next_subpage_id.clone(),
self.constellation_chan.clone()); self.constellation_chan.clone());