clean-up navigation

security: check target and source origin before executing JS url

implement replacement-enabled flag as a HistoryEntryReplacement enum

add source origin string on loaddata

add LoadOrigin

iframe: remove optional load-data

auxiliaries: add load-data into info

constellation: remove url from Pipeline::new

check load origin: link to whatwg issue

switch loadorigin toplevel to constellation
This commit is contained in:
Gregory Terzian 2019-05-12 17:37:19 +08:00
parent 973a3448a4
commit 571beec179
14 changed files with 402 additions and 220 deletions

View file

@ -37,8 +37,8 @@ use profile_traits::ipc as ProfiledIpc;
use script_layout_interface::message::ReflowGoal;
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
use script_traits::{
IFrameLoadInfo, IFrameLoadInfoWithData, JsEvalResult, LoadData, UpdatePipelineIdReason,
WindowSizeData,
HistoryEntryReplacement, IFrameLoadInfo, IFrameLoadInfoWithData, JsEvalResult, LoadData,
LoadOrigin, UpdatePipelineIdReason, WindowSizeData,
};
use script_traits::{NewLayoutInfo, ScriptMsg};
use servo_url::ServoUrl;
@ -109,9 +109,9 @@ impl HTMLIFrameElement {
pub fn navigate_or_reload_child_browsing_context(
&self,
mut load_data: Option<LoadData>,
mut load_data: LoadData,
nav_type: NavigationType,
replace: bool,
replace: HistoryEntryReplacement,
) {
let sandboxed = if self.is_sandboxed() {
IFrameSandboxed
@ -136,30 +136,27 @@ impl HTMLIFrameElement {
// document; the new navigation will continue blocking it.
LoadBlocker::terminate(&mut load_blocker);
if let Some(ref mut load_data) = load_data {
let is_javascript = load_data.url.scheme() == "javascript";
if is_javascript {
let window_proxy = self.GetContentWindow();
if let Some(window_proxy) = window_proxy {
ScriptThread::eval_js_url(&window_proxy.global(), load_data);
if load_data.url.scheme() == "javascript" {
let window_proxy = self.GetContentWindow();
if let Some(window_proxy) = window_proxy {
// Important re security. See https://github.com/servo/servo/issues/23373
// TODO: check according to https://w3c.github.io/webappsec-csp/#should-block-navigation-request
if ScriptThread::check_load_origin(&load_data.load_origin, &document.url().origin())
{
ScriptThread::eval_js_url(&window_proxy.global(), &mut load_data);
}
}
}
//TODO(#9592): Deal with the case where an iframe is being reloaded so url is None.
// The iframe should always have access to the nested context's active
// document URL through the browsing context.
if let Some(ref load_data) = load_data {
match load_data.js_eval_result {
Some(JsEvalResult::NoContent) => (),
_ => {
*load_blocker = Some(LoadBlocker::new(
&*document,
LoadType::Subframe(load_data.url.clone()),
));
},
};
}
match load_data.js_eval_result {
Some(JsEvalResult::NoContent) => (),
_ => {
*load_blocker = Some(LoadBlocker::new(
&*document,
LoadType::Subframe(load_data.url.clone()),
));
},
};
let window = window_from_node(self);
let old_pipeline_id = self.pipeline_id();
@ -182,6 +179,12 @@ impl HTMLIFrameElement {
self.about_blank_pipeline_id.set(Some(new_pipeline_id));
let load_info = IFrameLoadInfoWithData {
info: load_info,
load_data: load_data.clone(),
old_pipeline_id: old_pipeline_id,
sandbox: sandboxed,
};
global_scope
.script_to_constellation_chan()
.send(ScriptMsg::ScriptNewIFrame(load_info, pipeline_sender))
@ -193,7 +196,7 @@ impl HTMLIFrameElement {
browsing_context_id: browsing_context_id,
top_level_browsing_context_id: top_level_browsing_context_id,
opener: None,
load_data: load_data.unwrap(),
load_data: load_data,
pipeline_port: pipeline_receiver,
content_process_shutdown_chan: None,
window_size: WindowSizeData {
@ -270,6 +273,7 @@ impl HTMLIFrameElement {
let document = document_from_node(self);
let load_data = LoadData::new(
LoadOrigin::Script(document.origin().immutable().clone()),
url,
creator_pipeline_id,
Some(Referrer::ReferrerUrl(document.url())),
@ -281,12 +285,12 @@ impl HTMLIFrameElement {
// see https://html.spec.whatwg.org/multipage/#the-iframe-element:about:blank-3
let is_about_blank =
pipeline_id.is_some() && pipeline_id == self.about_blank_pipeline_id.get();
let replace = is_about_blank;
self.navigate_or_reload_child_browsing_context(
Some(load_data),
NavigationType::Regular,
replace,
);
let replace = if is_about_blank {
HistoryEntryReplacement::Enabled
} else {
HistoryEntryReplacement::Disabled
};
self.navigate_or_reload_child_browsing_context(load_data, NavigationType::Regular, replace);
}
fn create_nested_browsing_context(&self) {
@ -296,6 +300,7 @@ impl HTMLIFrameElement {
let window = window_from_node(self);
let pipeline_id = Some(window.upcast::<GlobalScope>().pipeline_id());
let load_data = LoadData::new(
LoadOrigin::Script(document.origin().immutable().clone()),
url,
pipeline_id,
Some(Referrer::ReferrerUrl(document.url().clone())),
@ -309,9 +314,9 @@ impl HTMLIFrameElement {
.set(Some(top_level_browsing_context_id));
self.browsing_context_id.set(Some(browsing_context_id));
self.navigate_or_reload_child_browsing_context(
Some(load_data),
load_data,
NavigationType::InitialAboutBlank,
false,
HistoryEntryReplacement::Disabled,
);
}