From 1a4ea09205646f25a6844567c840e066201cc4c3 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 3 Jul 2013 18:26:08 -0400 Subject: [PATCH 1/3] WIP iframe handling. --- src/components/script/dom/bindings/element.rs | 6 +- src/components/script/dom/element.rs | 8 +++ src/components/script/dom/node.rs | 20 ++++++- .../script/html/hubbub_html_parser.rs | 57 ++++++++++++++++++- 4 files changed, 85 insertions(+), 6 deletions(-) diff --git a/src/components/script/dom/bindings/element.rs b/src/components/script/dom/bindings/element.rs index b37c3f1a43b..e186e8c97ae 100644 --- a/src/components/script/dom/bindings/element.rs +++ b/src/components/script/dom/bindings/element.rs @@ -6,8 +6,10 @@ use dom::bindings::node::unwrap; use dom::bindings::utils::jsval_to_str; use dom::bindings::utils::{domstring_to_jsval, WrapNewBindingObject}; use dom::bindings::utils::{str, CacheableWrapper, DOM_OBJECT_SLOT, DOMString}; -use dom::element::*; -use dom::node::{AbstractNode, Element, ElementNodeTypeId, ScriptView}; +use dom::element::Element; +use dom::element::{HTMLImageElementTypeId, HTMLHeadElementTypeId, HTMLScriptElementTypeId, + HTMLDivElementTypeId}; +use dom::node::{AbstractNode, ScriptView, ElementNodeTypeId}; use layout_interface::{ContentBoxQuery, ContentBoxResponse}; use script_task::task_from_context; use super::utils; diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 2595a68657d..3983d1b83f2 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -8,6 +8,7 @@ use dom::bindings::utils::DOMString; use dom::clientrect::ClientRect; use dom::clientrectlist::ClientRectList; use dom::node::{ElementNodeTypeId, Node, ScriptView}; +use html::hubbub_html_parser::HtmlParserResult; use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery}; use layout_interface::{ContentBoxesResponse}; @@ -37,6 +38,7 @@ pub enum ElementTypeId { HTMLHeadElementTypeId, HTMLHeadingElementTypeId, HTMLHtmlElementTypeId, + HTMLIframeElementTypeId, HTMLImageElementTypeId, HTMLInputElementTypeId, HTMLItalicElementTypeId, @@ -107,6 +109,12 @@ pub struct HTMLHeadingElement { level: HeadingLevel, } +pub struct HTMLIframeElement { + parent: Element, + frame: Option, + parse_result: Option> +} + pub struct HTMLImageElement { parent: Element, image: Option, diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 87204414e4a..821e03d0197 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -10,7 +10,7 @@ use dom::bindings::utils::WrapperCache; use dom::bindings; use dom::characterdata::CharacterData; use dom::document::Document; -use dom::element::{Element, ElementTypeId, HTMLImageElement, HTMLImageElementTypeId}; +use dom::element::{Element, ElementTypeId, HTMLImageElement, HTMLImageElementTypeId, HTMLIframeElementTypeId, HTMLIframeElement}; use dom::element::{HTMLStyleElementTypeId}; use script_task::global_script_context; @@ -340,6 +340,24 @@ impl AbstractNode { self.transmute_mut(f) } + pub fn is_iframe_element(self) -> bool { + self.type_id() == ElementNodeTypeId(HTMLIframeElementTypeId) + } + + pub fn with_imm_iframe_element(self, f: &fn(&HTMLIframeElement) -> R) -> R { + if !self.is_iframe_element() { + fail!(~"node is not an iframe element"); + } + self.transmute(f) + } + + pub fn with_mut_iframe_element(self, f: &fn(&mut HTMLIframeElement) -> R) -> R { + if !self.is_iframe_element() { + fail!(~"node is not an iframe element"); + } + self.transmute_mut(f) + } + pub fn is_style_element(self) -> bool { self.type_id() == ElementNodeTypeId(HTMLStyleElementTypeId) } diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index da3a2c32e75..72eac9c51ed 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -2,8 +2,33 @@ * 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 dom::element::*; -use dom::node::{AbstractNode, Comment, Doctype, Element, ElementNodeTypeId, Node, ScriptView}; +use dom::element::{HTMLAnchorElementTypeId, HTMLAsideElementTypeId, HTMLBRElementTypeId, + HTMLBodyElementTypeId, HTMLBoldElementTypeId, HTMLDivElementTypeId, + HTMLFontElementTypeId, HTMLFormElementTypeId, HTMLHRElementTypeId, + HTMLHeadElementTypeId, HTMLHtmlElementTypeId, + HTMLImageElementTypeId, HTMLIframeElementTypeId, HTMLInputElementTypeId, + HTMLItalicElementTypeId, HTMLLinkElementTypeId, HTMLListItemElementTypeId, + HTMLMetaElementTypeId, HTMLOListElementTypeId, HTMLOptionElementTypeId, + HTMLParagraphElementTypeId, HTMLScriptElementTypeId, + HTMLSectionElementTypeId, HTMLSelectElementTypeId, HTMLSmallElementTypeId, + HTMLSpanElementTypeId, HTMLStyleElementTypeId, HTMLTableBodyElementTypeId, + HTMLTableCellElementTypeId, HTMLTableElementTypeId, + HTMLTableRowElementTypeId, HTMLTitleElementTypeId, HTMLUListElementTypeId, + UnknownElementTypeId}; +use dom::element::{HTMLAnchorElement, HTMLAsideElement, HTMLBRElement, HTMLBodyElement, + HTMLBoldElement, HTMLDivElement, HTMLFontElement, HTMLFormElement, + HTMLHRElement, HTMLHeadElement, HTMLHeadingElement, HTMLHtmlElement, + HTMLInputElement, HTMLImageElement, HTMLIframeElement, + HTMLItalicElement, HTMLLinkElement, HTMLListItemElement, HTMLMetaElement, + HTMLOListElement, HTMLOptionElement, HTMLParagraphElement, + HTMLScriptElement, HTMLSectionElement, HTMLSelectElement, HTMLSmallElement, + HTMLSpanElement, HTMLStyleElement, HTMLTableBodyElement, + HTMLTableCellElement, HTMLTableElement, HTMLTableRowElement, + HTMLTitleElement, HTMLUListElement}; +use dom::element::{HTMLHeadingElementTypeId, Heading1, Heading2, Heading3, Heading4, Heading5, + Heading6}; +use dom::element::{Element, Attr}; +use dom::node::{AbstractNode, Comment, Doctype, ElementNodeTypeId, Node, ScriptView}; use dom::node::{Text}; use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser}; use newcss::stylesheet::Stylesheet; @@ -52,7 +77,7 @@ enum JSMessage { JSTaskExit } -struct HtmlParserResult { +pub struct HtmlParserResult { root: AbstractNode, style_port: Port>, js_port: Port, @@ -194,6 +219,8 @@ fn build_element_from_tag(tag: &str) -> AbstractNode { handle_element!(tag, "ul", HTMLUListElementTypeId, HTMLUListElement, []); handle_element!(tag, "img", HTMLImageElementTypeId, HTMLImageElement, [(image: None)]); + handle_element!(tag, "iframe", HTMLIframeElementTypeId, HTMLIframeElement, + [(frame: None), (parse_result: None)]); handle_element!(tag, "h1", HTMLHeadingElementTypeId, HTMLHeadingElement, [(level: Heading1)]); handle_element!(tag, "h2", HTMLHeadingElementTypeId, HTMLHeadingElement, [(level: Heading2)]); @@ -213,6 +240,7 @@ pub fn parse_html(url: Url, image_cache_task: ImageCacheTask) -> HtmlParserResult { // Spawn a CSS parser to receive links to CSS style sheets. let resource_task2 = resource_task.clone(); + let resource_task3 = resource_task.clone(); let (stylesheet_port, stylesheet_chan) = comm::stream(); let stylesheet_chan = Cell::new(stylesheet_chan); @@ -314,6 +342,29 @@ pub fn parse_html(url: Url, } } }, + ElementNodeTypeId(HTMLIframeElementTypeId) => { + do node.with_mut_iframe_element |iframe_element| { + let src_opt = iframe_element.parent.get_attr("src").map(|x| x.to_str()); + match src_opt { + None => {} + Some(src) => { + let iframe_url = make_url(src, Some(url2.clone())); + iframe_element.frame = Some(iframe_url.clone()); + let (parse_port, parse_chan) = comm::stream(); + iframe_element.parse_result = Some(parse_port); + let image_cache_task2 = Cell::new(image_cache_task.clone()); + let resource_task3 = Cell::new(resource_task3.clone()); + let iframe_url = Cell::new(iframe_url); + do task::spawn { + let result = parse_html(iframe_url.take(), + resource_task3.take(), + image_cache_task2.take()); + parse_chan.send(result); + } + } + } + } + } ElementNodeTypeId(HTMLImageElementTypeId) => { do node.with_mut_image_element |image_element| { let src_opt = image_element.parent.get_attr("src").map(|x| x.to_str()); From 4815d8fccdc1affc1bccdc15584d299bce18e3d9 Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Wed, 10 Jul 2013 16:56:59 -0700 Subject: [PATCH 2/3] refactored url handling code in script task to be more idiomatic --- src/components/script/script_task.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 264dcefae76..0c5e9c4af4f 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -595,7 +595,7 @@ impl ScriptTask { match self.query_layout(HitTestQuery(root, point, chan), port) { Ok(node) => match node { HitTestResponse(node) => { - debug!("clicked on %?", node.debug_str()); + debug!("clicked on %s", node.debug_str()); let mut node = node; // traverse node generations until a node that is an element is found while !node.is_element() { @@ -608,9 +608,8 @@ impl ScriptTask { } if node.is_element() { do node.with_imm_element |element| { - match element.tag_name { - ~"a" => self.load_url_from_element(element), - _ => {} + if "a" == element.tag_name { + self.load_url_from_element(element) } } } @@ -628,16 +627,14 @@ impl ScriptTask { priv fn load_url_from_element(&self, element: &Element) { // if the node's element is "a," load url from href attr - for element.attrs.iter().advance |attr| { - if attr.name == ~"href" { - debug!("clicked on link to %?", attr.value); - let current_url = match self.root_frame { - Some(ref frame) => Some(frame.url.clone()), - None => None - }; - let url = make_url(attr.value.clone(), current_url); - self.constellation_chan.send(LoadUrlMsg(url)); - } + let href = element.get_attr("href"); + for href.iter().advance |href| { + debug!("clicked on link to %s", *href); + let current_url = do self.root_frame.map |frame| { + frame.url.clone() + }; + let url = make_url(href.to_owned(), current_url); + self.constellation_chan.send(LoadUrlMsg(url)); } } } From c32358593f175139356781552182cfc5a1ecca9e Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Thu, 11 Jul 2013 13:15:21 -0700 Subject: [PATCH 3/3] fixed navigation bug --- src/components/main/constellation.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/main/constellation.rs b/src/components/main/constellation.rs index 8c4ab3d89d9..91f642f4e8e 100644 --- a/src/components/main/constellation.rs +++ b/src/components/main/constellation.rs @@ -4,6 +4,8 @@ use compositing::{CompositorChan, SetLayoutRenderChans}; +use extra::net::url; + use std::cell::Cell; use std::comm; use std::comm::Port; @@ -60,19 +62,20 @@ impl NavigationContext { pub fn back(&mut self) -> uint { self.next.push(self.current.get()); self.current = Some(self.previous.pop()); - debug!("previous: %? next: %? current: %?", self.previous, self.next, self.current); + debug!("previous: %? next: %? current: %u", self.previous, self.next, self.current.get()); self.current.get() } pub fn forward(&mut self) -> uint { self.previous.push(self.current.get()); self.current = Some(self.next.pop()); - debug!("previous: %? next: %? current: %?", self.previous, self.next, self.current); + debug!("previous: %? next: %? current: %u", self.previous, self.next, self.current.get()); self.current.get() } /// Navigates to a new id, returning all id's evicted from next pub fn navigate(&mut self, id: uint) -> ~[uint] { + debug!("navigating to %u", id); let evicted = replace(&mut self.next, ~[]); do self.current.mutate_default(id) |cur_id| { self.previous.push(cur_id); @@ -143,6 +146,7 @@ impl Constellation { match request { // Load a new page, usually either from a mouse click or typed url LoadUrlMsg(url) => { + debug!("received message to load %s", url::to_str(&url)); let pipeline_id = self.get_next_id(); let mut pipeline = Pipeline::create(pipeline_id, self.chan.clone(), @@ -180,7 +184,6 @@ impl Constellation { self.navigation_context.back() } }; - debug!("navigating to pipeline %u", destination_id); let mut pipeline = self.pipelines.pop(&destination_id).unwrap(); pipeline.navigation_type = Some(constellation_msg::Navigate); pipeline.reload(); @@ -234,7 +237,8 @@ impl Constellation { for current_painter.iter().advance |id| { self.pipelines.get(id).render_chan.send(PaintPermissionRevoked); } - let id = self.next_painter.get(); + let id = replace(&mut self.next_painter, None); + let id = id.expect("constellation: called update painter when there was no next painter"); let pipeline = self.pipelines.get(&id); self.compositor_chan.send(SetLayoutRenderChans(pipeline.layout_chan.clone(), pipeline.render_chan.clone(), @@ -247,7 +251,6 @@ impl Constellation { let pipeline = self.pipelines.get(&id); pipeline.render_chan.send(PaintPermissionGranted); self.current_painter = Some(id); - self.next_painter = None; // Don't navigate on Navigate type, because that is handled by forward/back match pipeline.navigation_type.get() { constellation_msg::Load => {