diff options
Diffstat (limited to 'components/script/script_task.rs')
-rw-r--r-- | components/script/script_task.rs | 88 |
1 files changed, 86 insertions, 2 deletions
diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 7da46d628ce..688a89757c2 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -51,7 +51,8 @@ use servo_msg::constellation_msg::{KeyModifiers, SUPER, SHIFT, CONTROL, ALT, Rep use servo_msg::constellation_msg::{Released}; use servo_msg::constellation_msg; use servo_net::image_cache_task::ImageCacheTask; -use servo_net::resource_task::ResourceTask; +use servo_net::resource_task::{ResourceTask, Load}; +use servo_net::resource_task::LoadData as NetLoadData; use servo_net::storage_task::StorageTask; use servo_util::geometry::to_frac_px; use servo_util::smallvec::{SmallVec1, SmallVec}; @@ -59,6 +60,8 @@ use servo_util::task::spawn_named_with_send_on_failure; use servo_util::task_state; use geom::point::Point2D; +use hyper::header::{Header, HeaderFormat}; +use hyper::header::common::util as header_util; use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC}; use js::jsapi::{JSContext, JSRuntime, JSTracer}; use js::jsapi::{JS_SetGCParameter, JSGC_MAX_BYTES}; @@ -71,9 +74,11 @@ use libc::size_t; use std::any::{Any, AnyRefExt}; use std::collections::HashSet; use std::comm::{channel, Sender, Receiver, Select}; +use std::fmt::{mod, Show}; use std::mem::replace; use std::rc::Rc; use std::u32; +use time::{Tm, strptime}; local_data_key!(pub StackRoots: *const RootCollection) @@ -748,7 +753,47 @@ impl ScriptTask { InputString(strval.unwrap_or("".to_string())) }; - parse_html(&*page, *document, parser_input, self.resource_task.clone(), load_data); + let (base_url, load_response) = match parser_input { + InputUrl(ref url) => { + // Wait for the LoadResponse so that the parser knows the final URL. + let (input_chan, input_port) = channel(); + self.resource_task.send(Load(NetLoadData { + url: url.clone(), + method: load_data.method, + headers: load_data.headers, + data: load_data.data, + cors: None, + consumer: input_chan, + })); + + let load_response = input_port.recv(); + + load_response.metadata.headers.as_ref().map(|headers| { + headers.get().map(|&LastModified(ref tm)| { + document.set_last_modified(dom_last_modified(tm)); + }); + }); + + let base_url = load_response.metadata.final_url.clone(); + + { + // Store the final URL before we start parsing, so that DOM routines + // (e.g. HTMLImageElement::update_image) can resolve relative URLs + // correctly. + *page.mut_url() = Some((base_url.clone(), true)); + } + + (Some(base_url), Some(load_response)) + }, + InputString(_) => { + match *page.url() { + Some((ref page_url, _)) => (Some(page_url.clone()), None), + None => (None, None), + } + }, + }; + + parse_html(*document, parser_input, base_url, load_response); url = page.get_url().clone(); document.set_ready_state(DocumentReadyStateValues::Interactive); @@ -1159,3 +1204,42 @@ pub fn get_page(page: &Rc<Page>, pipeline_id: PipelineId) -> Rc<Page> { message for a layout channel that is not associated with this script task.\ This is a bug.") } + +//FIXME(seanmonstar): uplift to Hyper +#[deriving(Clone)] +struct LastModified(pub Tm); + +impl Header for LastModified { + #[inline] + fn header_name(_: Option<LastModified>) -> &'static str { + "Last-Modified" + } + + // Parses an RFC 2616 compliant date/time string, + fn parse_header(raw: &[Vec<u8>]) -> Option<LastModified> { + header_util::from_one_raw_str(raw).and_then(|s: String| { + let s = s.as_slice(); + strptime(s, "%a, %d %b %Y %T %Z").or_else(|_| { + strptime(s, "%A, %d-%b-%y %T %Z") + }).or_else(|_| { + strptime(s, "%c") + }).ok().map(|tm| LastModified(tm)) + }) + } +} + +impl HeaderFormat for LastModified { + // a localized date/time string in a format suitable + // for document.lastModified. + fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { + let LastModified(ref tm) = *self; + match tm.tm_gmtoff { + 0 => tm.rfc822().fmt(f), + _ => tm.to_utc().rfc822().fmt(f) + } + } +} + +fn dom_last_modified(tm: &Tm) -> String { + tm.to_local().strftime("%m/%d/%Y %H:%M:%S").unwrap() +} |