mirror of
https://github.com/servo/servo.git
synced 2025-06-19 22:59:03 +01:00
Make sandboxed iframes run with different script tasks.
This commit is contained in:
parent
25a3d4a93f
commit
9640324721
9 changed files with 123 additions and 22 deletions
|
@ -13,9 +13,9 @@ use geom::size::Size2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::opts::Opts;
|
use gfx::opts::Opts;
|
||||||
use pipeline::Pipeline;
|
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::{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::{PipelineId, RendererReadyMsg, ResizedWindowMsg, SubpageId};
|
||||||
use servo_msg::constellation_msg;
|
use servo_msg::constellation_msg;
|
||||||
use script::script_task::{SendEventMsg, ResizeInactiveMsg, ExecuteMsg};
|
use script::script_task::{SendEventMsg, ResizeInactiveMsg, ExecuteMsg};
|
||||||
|
@ -328,8 +328,8 @@ impl Constellation {
|
||||||
FrameRectMsg(pipeline_id, subpage_id, rect) => {
|
FrameRectMsg(pipeline_id, subpage_id, rect) => {
|
||||||
self.handle_frame_rect_msg(pipeline_id, subpage_id, rect);
|
self.handle_frame_rect_msg(pipeline_id, subpage_id, rect);
|
||||||
}
|
}
|
||||||
LoadIframeUrlMsg(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);
|
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
|
// 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;
|
// If there is already a pending page (self.pending_frames), it will not be overridden;
|
||||||
|
@ -455,7 +455,8 @@ impl Constellation {
|
||||||
url: Url,
|
url: Url,
|
||||||
source_pipeline_id: PipelineId,
|
source_pipeline_id: PipelineId,
|
||||||
subpage_id: SubpageId,
|
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
|
// A message from the script associated with pipeline_id that it has
|
||||||
// parsed an iframe during html parsing. This iframe will result in a
|
// 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
|
// 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
|
source's Url is None. There should never be a LoadUrlIframeMsg from a pipeline
|
||||||
that was never given a url to load.");
|
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
|
// FIXME(tkuehn): Need to follow the standardized spec for checking same-origin
|
||||||
let pipeline = @mut if (source_url.host == url.host &&
|
let pipeline = @mut if same_script {
|
||||||
source_url.port == url.port) {
|
|
||||||
debug!("Constellation: loading same-origin iframe at %?", url);
|
debug!("Constellation: loading same-origin iframe at %?", url);
|
||||||
// Reuse the script task if same-origin url's
|
// Reuse the script task if same-origin url's
|
||||||
Pipeline::with_script(next_pipeline_id,
|
Pipeline::with_script(next_pipeline_id,
|
||||||
|
|
|
@ -27,12 +27,18 @@ impl ConstellationChan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Eq)]
|
||||||
|
pub enum IFrameSandboxState {
|
||||||
|
IFrameSandboxed,
|
||||||
|
IFrameUnsandboxed
|
||||||
|
}
|
||||||
|
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
ExitMsg(Chan<()>),
|
ExitMsg(Chan<()>),
|
||||||
InitLoadUrlMsg(Url),
|
InitLoadUrlMsg(Url),
|
||||||
FrameRectMsg(PipelineId, SubpageId, Rect<f32>),
|
FrameRectMsg(PipelineId, SubpageId, Rect<f32>),
|
||||||
LoadUrlMsg(PipelineId, Url, Future<Size2D<uint>>),
|
LoadUrlMsg(PipelineId, Url, Future<Size2D<uint>>),
|
||||||
LoadIframeUrlMsg(Url, PipelineId, SubpageId, Future<Size2D<uint>>),
|
LoadIframeUrlMsg(Url, PipelineId, SubpageId, Future<Size2D<uint>>, IFrameSandboxState),
|
||||||
NavigateMsg(NavigationDirection),
|
NavigateMsg(NavigationDirection),
|
||||||
RendererReadyMsg(PipelineId),
|
RendererReadyMsg(PipelineId),
|
||||||
ResizedWindowMsg(Size2D<uint>),
|
ResizedWindowMsg(Size2D<uint>),
|
||||||
|
|
|
@ -139,9 +139,9 @@ impl<'self> Element {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_attr(&mut self, name: &DOMString, value: &DOMString) {
|
pub fn set_attr(&mut self, raw_name: &DOMString, raw_value: &DOMString) {
|
||||||
let name = name.to_str();
|
let name = raw_name.to_str();
|
||||||
let value_cell = Cell::new(value.to_str());
|
let value_cell = Cell::new(raw_value.to_str());
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
for attr in self.attrs.mut_iter() {
|
for attr in self.attrs.mut_iter() {
|
||||||
if eq_slice(attr.name, name) {
|
if eq_slice(attr.name, name) {
|
||||||
|
@ -158,7 +158,15 @@ impl<'self> Element {
|
||||||
self.style_attribute = Some(
|
self.style_attribute = Some(
|
||||||
Stylesheet::from_attribute(
|
Stylesheet::from_attribute(
|
||||||
FromStr::from_str("http://www.example.com/").unwrap(),
|
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 {
|
match self.parent.owner_doc {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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::document::AbstractDocument;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::windowproxy::WindowProxy;
|
use dom::windowproxy::WindowProxy;
|
||||||
|
@ -11,14 +11,26 @@ use geom::rect::Rect;
|
||||||
|
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg, PipelineId, SubpageId};
|
use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg, PipelineId, SubpageId};
|
||||||
|
|
||||||
|
use std::ascii::StrAsciiExt;
|
||||||
use std::comm::ChanOne;
|
use std::comm::ChanOne;
|
||||||
use extra::url::Url;
|
use extra::url::Url;
|
||||||
use std::util::replace;
|
use std::util::replace;
|
||||||
|
|
||||||
|
enum SandboxAllowance {
|
||||||
|
AllowNothing = 0x00,
|
||||||
|
AllowSameOrigin = 0x01,
|
||||||
|
AllowTopNavigation = 0x02,
|
||||||
|
AllowForms = 0x04,
|
||||||
|
AllowScripts = 0x08,
|
||||||
|
AllowPointerLock = 0x10,
|
||||||
|
AllowPopups = 0x20
|
||||||
|
}
|
||||||
|
|
||||||
pub struct HTMLIFrameElement {
|
pub struct HTMLIFrameElement {
|
||||||
parent: HTMLElement,
|
parent: HTMLElement,
|
||||||
frame: Option<Url>,
|
frame: Option<Url>,
|
||||||
size: Option<IFrameSize>,
|
size: Option<IFrameSize>,
|
||||||
|
sandbox: Option<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IFrameSize {
|
struct IFrameSize {
|
||||||
|
@ -39,6 +51,11 @@ impl IFrameSize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HTMLIFrameElement {
|
||||||
|
pub fn is_sandboxed(&self) -> bool {
|
||||||
|
self.sandbox.is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HTMLIFrameElement {
|
impl HTMLIFrameElement {
|
||||||
pub fn Src(&self) -> DOMString {
|
pub fn Src(&self) -> DOMString {
|
||||||
|
@ -63,10 +80,32 @@ impl HTMLIFrameElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Sandbox(&self) -> DOMString {
|
pub fn Sandbox(&self) -> DOMString {
|
||||||
null_string
|
self.parent.parent.GetAttribute(&str(~"sandbox"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn SetSandbox(&self, _sandbox: &DOMString) {
|
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 {
|
pub fn AllowFullscreen(&self) -> bool {
|
||||||
|
|
|
@ -93,7 +93,7 @@ enum JSMessage {
|
||||||
/// Messages generated by the HTML parser upon discovery of additional resources
|
/// Messages generated by the HTML parser upon discovery of additional resources
|
||||||
pub enum HtmlDiscoveryMessage {
|
pub enum HtmlDiscoveryMessage {
|
||||||
HtmlDiscoveredStyle(Stylesheet),
|
HtmlDiscoveredStyle(Stylesheet),
|
||||||
HtmlDiscoveredIFrame((Url, SubpageId, Future<Size2D<uint>>)),
|
HtmlDiscoveredIFrame((Url, SubpageId, Future<Size2D<uint>>, bool)),
|
||||||
HtmlDiscoveredScript(JSResult)
|
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, "ul", HTMLUListElementTypeId, HTMLUListElement, []);
|
||||||
|
|
||||||
handle_element!(cx, tag, "img", HTMLImageElementTypeId, HTMLImageElement, [(image: None)]);
|
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, "h1", HTMLHeadingElementTypeId, HTMLHeadingElement, [(level: Heading1)]);
|
||||||
handle_element!(cx, tag, "h2", HTMLHeadingElementTypeId, HTMLHeadingElement, [(level: Heading2)]);
|
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());
|
let iframe_chan = Cell::new(discovery_chan.clone());
|
||||||
do node.with_mut_iframe_element |iframe_element| {
|
do node.with_mut_iframe_element |iframe_element| {
|
||||||
let iframe_chan = iframe_chan.take();
|
let iframe_chan = iframe_chan.take();
|
||||||
|
let sandboxed = iframe_element.is_sandboxed();
|
||||||
let elem = &mut iframe_element.parent.parent;
|
let elem = &mut iframe_element.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());
|
||||||
for src in src_opt.iter() {
|
for src in src_opt.iter() {
|
||||||
|
@ -427,7 +428,8 @@ pub fn parse_html(cx: *JSContext,
|
||||||
future_chan: Some(chan),
|
future_chan: Some(chan),
|
||||||
constellation_chan: constellation_chan.clone(),
|
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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ use layout_interface::ReflowMsg;
|
||||||
use layout_interface;
|
use layout_interface;
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, LoadUrlMsg, NavigationDirection};
|
use servo_msg::constellation_msg::{ConstellationChan, LoadUrlMsg, NavigationDirection};
|
||||||
use servo_msg::constellation_msg::{PipelineId, SubpageId, RendererReadyMsg};
|
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 servo_msg::constellation_msg;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -641,12 +641,18 @@ impl ScriptTask {
|
||||||
Some(HtmlDiscoveredStyle(sheet)) => {
|
Some(HtmlDiscoveredStyle(sheet)) => {
|
||||||
page.layout_chan.send(AddStylesheetMsg(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);
|
page.next_subpage_id = SubpageId(*subpage_id + 1);
|
||||||
|
let sandboxed = if sandboxed {
|
||||||
|
IFrameSandboxed
|
||||||
|
} else {
|
||||||
|
IFrameUnsandboxed
|
||||||
|
};
|
||||||
self.constellation_chan.send(LoadIframeUrlMsg(iframe_url,
|
self.constellation_chan.send(LoadIframeUrlMsg(iframe_url,
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
subpage_id,
|
subpage_id,
|
||||||
size_future));
|
size_future,
|
||||||
|
sandboxed));
|
||||||
}
|
}
|
||||||
None => break
|
None => break
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 353ef00db32e526f054f1f7899cd93425cfb1c59
|
Subproject commit a9bc3b5cf968e279cfb082e58207c60e4f4a1a9b
|
14
src/test/html/test_sandboxed.html
Normal file
14
src/test/html/test_sandboxed.html
Normal file
|
@ -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>
|
24
src/test/html/test_sandboxed_iframe.html
Normal file
24
src/test/html/test_sandboxed_iframe.html
Normal file
|
@ -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>
|
Loading…
Add table
Add a link
Reference in a new issue