diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/main/constellation.rs | 16 | ||||
-rw-r--r-- | src/components/msg/constellation_msg.rs | 8 | ||||
-rw-r--r-- | src/components/script/dom/element.rs | 16 | ||||
-rw-r--r-- | src/components/script/dom/htmliframeelement.rs | 49 | ||||
-rw-r--r-- | src/components/script/html/hubbub_html_parser.rs | 8 | ||||
-rw-r--r-- | src/components/script/script_task.rs | 12 | ||||
m--------- | src/support/spidermonkey/rust-mozjs | 0 | ||||
-rw-r--r-- | src/test/html/test_sandboxed.html | 14 | ||||
-rw-r--r-- | src/test/html/test_sandboxed_iframe.html | 24 |
9 files changed, 124 insertions, 23 deletions
diff --git a/src/components/main/constellation.rs b/src/components/main/constellation.rs index 7ae71478306..271b72526bb 100644 --- a/src/components/main/constellation.rs +++ b/src/components/main/constellation.rs @@ -13,9 +13,9 @@ use geom::size::Size2D; use geom::rect::Rect; use gfx::opts::Opts; use pipeline::Pipeline; -use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FrameRectMsg}; +use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FrameRectMsg, IFrameSandboxState}; use servo_msg::constellation_msg::{InitLoadUrlMsg, LoadIframeUrlMsg, LoadUrlMsg}; -use servo_msg::constellation_msg::{Msg, NavigateMsg, NavigationType}; +use servo_msg::constellation_msg::{Msg, NavigateMsg, NavigationType, IFrameUnsandboxed}; use servo_msg::constellation_msg::{PipelineId, RendererReadyMsg, ResizedWindowMsg, SubpageId}; use servo_msg::constellation_msg; use script::script_task::{SendEventMsg, ResizeInactiveMsg, ExecuteMsg}; @@ -328,8 +328,8 @@ impl Constellation { FrameRectMsg(pipeline_id, subpage_id, rect) => { self.handle_frame_rect_msg(pipeline_id, subpage_id, rect); } - LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, size_future) => { - self.handle_load_iframe_url_msg(url, source_pipeline_id, subpage_id, size_future); + LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, size_future, sandbox) => { + self.handle_load_iframe_url_msg(url, source_pipeline_id, subpage_id, size_future, sandbox); } // Load a new page, usually -- but not always -- from a mouse click or typed url // If there is already a pending page (self.pending_frames), it will not be overridden; @@ -455,7 +455,8 @@ impl Constellation { url: Url, source_pipeline_id: PipelineId, subpage_id: SubpageId, - size_future: Future<Size2D<uint>>) { + size_future: Future<Size2D<uint>>, + sandbox: IFrameSandboxState) { // A message from the script associated with pipeline_id that it has // parsed an iframe during html parsing. This iframe will result in a // new pipeline being spawned and a frame tree being added to pipeline_id's @@ -489,9 +490,10 @@ impl Constellation { source's Url is None. There should never be a LoadUrlIframeMsg from a pipeline that was never given a url to load."); + let same_script = (source_url.host == url.host && + source_url.port == url.port) && sandbox == IFrameUnsandboxed; // FIXME(tkuehn): Need to follow the standardized spec for checking same-origin - let pipeline = @mut if (source_url.host == url.host && - source_url.port == url.port) { + let pipeline = @mut if same_script { debug!("Constellation: loading same-origin iframe at %?", url); // Reuse the script task if same-origin url's Pipeline::with_script(next_pipeline_id, diff --git a/src/components/msg/constellation_msg.rs b/src/components/msg/constellation_msg.rs index 51bcbb08c46..c5b4dbb48d0 100644 --- a/src/components/msg/constellation_msg.rs +++ b/src/components/msg/constellation_msg.rs @@ -27,12 +27,18 @@ impl ConstellationChan { } } +#[deriving(Eq)] +pub enum IFrameSandboxState { + IFrameSandboxed, + IFrameUnsandboxed +} + pub enum Msg { ExitMsg(Chan<()>), InitLoadUrlMsg(Url), FrameRectMsg(PipelineId, SubpageId, Rect<f32>), LoadUrlMsg(PipelineId, Url, Future<Size2D<uint>>), - LoadIframeUrlMsg(Url, PipelineId, SubpageId, Future<Size2D<uint>>), + LoadIframeUrlMsg(Url, PipelineId, SubpageId, Future<Size2D<uint>>, IFrameSandboxState), NavigateMsg(NavigationDirection), RendererReadyMsg(PipelineId), ResizedWindowMsg(Size2D<uint>), diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index be475bd1d85..0bb776628c9 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -139,9 +139,9 @@ impl<'self> Element { return None; } - pub fn set_attr(&mut self, name: &DOMString, value: &DOMString) { - let name = name.to_str(); - let value_cell = Cell::new(value.to_str()); + pub fn set_attr(&mut self, raw_name: &DOMString, raw_value: &DOMString) { + let name = raw_name.to_str(); + let value_cell = Cell::new(raw_value.to_str()); let mut found = false; for attr in self.attrs.mut_iter() { if eq_slice(attr.name, name) { @@ -158,7 +158,15 @@ impl<'self> Element { self.style_attribute = Some( Stylesheet::from_attribute( FromStr::from_str("http://www.example.com/").unwrap(), - value.get_ref())); + raw_value.get_ref())); + } + + //XXXjdm We really need something like a vtable so we can call AfterSetAttr. + // This hardcoding is awful. + if self.parent.abstract.unwrap().is_iframe_element() { + do self.parent.abstract.unwrap().with_mut_iframe_element |iframe| { + iframe.AfterSetAttr(raw_name, raw_value); + } } match self.parent.owner_doc { diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs index 288a988928a..4c45e570b54 100644 --- a/src/components/script/dom/htmliframeelement.rs +++ b/src/components/script/dom/htmliframeelement.rs @@ -2,7 +2,7 @@ * 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::bindings::utils::{DOMString, null_string, ErrorResult}; +use dom::bindings::utils::{DOMString, null_string, ErrorResult, str}; use dom::document::AbstractDocument; use dom::htmlelement::HTMLElement; use dom::windowproxy::WindowProxy; @@ -11,14 +11,26 @@ use geom::rect::Rect; use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg, PipelineId, SubpageId}; +use std::ascii::StrAsciiExt; use std::comm::ChanOne; use extra::url::Url; use std::util::replace; +enum SandboxAllowance { + AllowNothing = 0x00, + AllowSameOrigin = 0x01, + AllowTopNavigation = 0x02, + AllowForms = 0x04, + AllowScripts = 0x08, + AllowPointerLock = 0x10, + AllowPopups = 0x20 +} + pub struct HTMLIFrameElement { parent: HTMLElement, frame: Option<Url>, size: Option<IFrameSize>, + sandbox: Option<u8> } struct IFrameSize { @@ -39,6 +51,11 @@ impl IFrameSize { } } +impl HTMLIFrameElement { + pub fn is_sandboxed(&self) -> bool { + self.sandbox.is_some() + } +} impl HTMLIFrameElement { pub fn Src(&self) -> DOMString { @@ -63,10 +80,32 @@ impl HTMLIFrameElement { } pub fn Sandbox(&self) -> DOMString { - null_string - } - - pub fn SetSandbox(&self, _sandbox: &DOMString) { + self.parent.parent.GetAttribute(&str(~"sandbox")) + } + + pub fn SetSandbox(&mut self, sandbox: &DOMString) { + let mut rv = Ok(()); + self.parent.parent.SetAttribute(&str(~"sandbox"), sandbox, &mut rv); + } + + pub fn AfterSetAttr(&mut self, name: &DOMString, value: &DOMString) { + let name = name.to_str(); + if "sandbox" == name { + let mut modes = AllowNothing as u8; + let words = value.to_str(); + for word in words.split_iter(' ') { + modes |= match word.to_ascii_lower().as_slice() { + "allow-same-origin" => AllowSameOrigin, + "allow-forms" => AllowForms, + "allow-pointer-lock" => AllowPointerLock, + "allow-popups" => AllowPopups, + "allow-scripts" => AllowScripts, + "allow-top-navigation" => AllowTopNavigation, + _ => AllowNothing + } as u8; + } + self.sandbox = Some(modes); + } } pub fn AllowFullscreen(&self) -> bool { diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index 64340a28b77..42c9e43cf48 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -93,7 +93,7 @@ enum JSMessage { /// Messages generated by the HTML parser upon discovery of additional resources pub enum HtmlDiscoveryMessage { HtmlDiscoveredStyle(Stylesheet), - HtmlDiscoveredIFrame((Url, SubpageId, Future<Size2D<uint>>)), + HtmlDiscoveredIFrame((Url, SubpageId, Future<Size2D<uint>>, bool)), HtmlDiscoveredScript(JSResult) } @@ -272,7 +272,7 @@ pub fn build_element_from_tag(cx: *JSContext, tag: &str) -> AbstractNode<ScriptV handle_element!(cx, tag, "ul", HTMLUListElementTypeId, HTMLUListElement, []); handle_element!(cx, tag, "img", HTMLImageElementTypeId, HTMLImageElement, [(image: None)]); - handle_element!(cx, tag, "iframe", HTMLIframeElementTypeId, HTMLIFrameElement, [(frame: None), (size: None)]); + handle_element!(cx, tag, "iframe", HTMLIframeElementTypeId, HTMLIFrameElement, [(frame: None), (size: None), (sandbox: None)]); handle_element!(cx, tag, "h1", HTMLHeadingElementTypeId, HTMLHeadingElement, [(level: Heading1)]); handle_element!(cx, tag, "h2", HTMLHeadingElementTypeId, HTMLHeadingElement, [(level: Heading2)]); @@ -401,6 +401,7 @@ pub fn parse_html(cx: *JSContext, let iframe_chan = Cell::new(discovery_chan.clone()); do node.with_mut_iframe_element |iframe_element| { let iframe_chan = iframe_chan.take(); + let sandboxed = iframe_element.is_sandboxed(); let elem = &mut iframe_element.parent.parent; let src_opt = elem.get_attr("src").map(|x| x.to_str()); for src in src_opt.iter() { @@ -427,7 +428,8 @@ pub fn parse_html(cx: *JSContext, future_chan: Some(chan), constellation_chan: constellation_chan.clone(), }); - iframe_chan.send(HtmlDiscoveredIFrame((iframe_url, subpage_id, size_future))); + iframe_chan.send(HtmlDiscoveredIFrame((iframe_url, subpage_id, + size_future, sandboxed))); } } } diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 759d37a6dc4..9d45dc7d8dc 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -22,7 +22,7 @@ use layout_interface::ReflowMsg; use layout_interface; use servo_msg::constellation_msg::{ConstellationChan, LoadUrlMsg, NavigationDirection}; use servo_msg::constellation_msg::{PipelineId, SubpageId, RendererReadyMsg}; -use servo_msg::constellation_msg::{LoadIframeUrlMsg}; +use servo_msg::constellation_msg::{LoadIframeUrlMsg, IFrameSandboxed, IFrameUnsandboxed}; use servo_msg::constellation_msg; use std::cell::Cell; @@ -641,12 +641,18 @@ impl ScriptTask { Some(HtmlDiscoveredStyle(sheet)) => { page.layout_chan.send(AddStylesheetMsg(sheet)); } - Some(HtmlDiscoveredIFrame((iframe_url, subpage_id, size_future))) => { + Some(HtmlDiscoveredIFrame((iframe_url, subpage_id, size_future, sandboxed))) => { page.next_subpage_id = SubpageId(*subpage_id + 1); + let sandboxed = if sandboxed { + IFrameSandboxed + } else { + IFrameUnsandboxed + }; self.constellation_chan.send(LoadIframeUrlMsg(iframe_url, pipeline_id, subpage_id, - size_future)); + size_future, + sandboxed)); } None => break } diff --git a/src/support/spidermonkey/rust-mozjs b/src/support/spidermonkey/rust-mozjs -Subproject 353ef00db32e526f054f1f7899cd93425cfb1c5 +Subproject a9bc3b5cf968e279cfb082e58207c60e4f4a1a9 diff --git a/src/test/html/test_sandboxed.html b/src/test/html/test_sandboxed.html new file mode 100644 index 00000000000..f0c485b5794 --- /dev/null +++ b/src/test/html/test_sandboxed.html @@ -0,0 +1,14 @@ +<html> +<body> + <iframe sandbox="allow-scripts" src="test_sandboxed_iframe.html" + style="display:block; border: 1px; width: 400px; height: 400px" + frameborder="yes" + scrolling="yes"></iframe> +hiiiiiiiii + <iframe sandbox="allow-scripts" src="test_sandboxed_iframe.html" + style="display:block; border: 1px; width: 400px; height: 400px" + frameborder="yes" + scrolling="yes"></iframe> +byeeeeeeeeeeee +</body> +</html> diff --git a/src/test/html/test_sandboxed_iframe.html b/src/test/html/test_sandboxed_iframe.html new file mode 100644 index 00000000000..210a6134a1b --- /dev/null +++ b/src/test/html/test_sandboxed_iframe.html @@ -0,0 +1,24 @@ +<html> +<body> + <script> + var a = 1; + var b = 1; + var c = 2; + var step = 1; + window.alert(Date.now()); + var next = new Date(); + window.alert(next); + while (true) { + if ((new Date()) >= next) { + window.alert("step " + step + ": " + c); + a = b; + b = c; + c = a + b; + step++; + next = new Date(Date.now() + 500); + } + } + </script> +hi there +</body> +</html> |