mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
"javascript:" urls: evaluate in iframe src attribute
- generalize the eval_js_url function so it can be called from multiple places. - call it in htmliframeelement. - if the js eval results in a non-string result, then it won't navigate to a new page, so don't block on the new page loading.
This commit is contained in:
parent
5d28dd64d9
commit
6ae6031468
3 changed files with 41 additions and 28 deletions
|
@ -1056,7 +1056,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
self.handle_load_url_msg(source_top_ctx_id, source_pipeline_id, load_data, replace);
|
self.handle_load_url_msg(source_top_ctx_id, source_pipeline_id, load_data, replace);
|
||||||
}
|
}
|
||||||
FromScriptMsg::AbortLoadUrl => {
|
FromScriptMsg::AbortLoadUrl => {
|
||||||
debug!("constellation got URL load message from script");
|
debug!("constellation got abort URL load message from script");
|
||||||
self.handle_abort_load_url_msg(source_pipeline_id);
|
self.handle_abort_load_url_msg(source_pipeline_id);
|
||||||
}
|
}
|
||||||
// A page loaded has completed all parsing, script, and reflow messages have been sent.
|
// A page loaded has completed all parsing, script, and reflow messages have been sent.
|
||||||
|
|
|
@ -44,7 +44,7 @@ use msg::constellation_msg::{FrameType, BrowsingContextId, PipelineId, TopLevelB
|
||||||
use net_traits::response::HttpsState;
|
use net_traits::response::HttpsState;
|
||||||
use script_layout_interface::message::ReflowQueryType;
|
use script_layout_interface::message::ReflowQueryType;
|
||||||
use script_thread::{ScriptThread, Runnable};
|
use script_thread::{ScriptThread, Runnable};
|
||||||
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, LoadData, UpdatePipelineIdReason};
|
use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, JsEvalResult, LoadData, UpdatePipelineIdReason};
|
||||||
use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg};
|
use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg};
|
||||||
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
||||||
use servo_atoms::Atom;
|
use servo_atoms::Atom;
|
||||||
|
@ -114,7 +114,7 @@ impl HTMLIFrameElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn navigate_or_reload_child_browsing_context(&self,
|
pub fn navigate_or_reload_child_browsing_context(&self,
|
||||||
load_data: Option<LoadData>,
|
mut load_data: Option<LoadData>,
|
||||||
nav_type: NavigationType,
|
nav_type: NavigationType,
|
||||||
replace: bool) {
|
replace: bool) {
|
||||||
let sandboxed = if self.is_sandboxed() {
|
let sandboxed = if self.is_sandboxed() {
|
||||||
|
@ -140,11 +140,26 @@ impl HTMLIFrameElement {
|
||||||
// document; the new navigation will continue blocking it.
|
// document; the new navigation will continue blocking it.
|
||||||
LoadBlocker::terminate(&mut load_blocker);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//TODO(#9592): Deal with the case where an iframe is being reloaded so url is None.
|
//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
|
// The iframe should always have access to the nested context's active
|
||||||
// document URL through the browsing context.
|
// document URL through the browsing context.
|
||||||
if let Some(ref load_data) = load_data {
|
if let Some(ref load_data) = load_data {
|
||||||
*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 window = window_from_node(self);
|
||||||
|
|
|
@ -2312,7 +2312,10 @@ impl ScriptThread {
|
||||||
replace: bool) {
|
replace: bool) {
|
||||||
let is_javascript = load_data.url.scheme() == "javascript";
|
let is_javascript = load_data.url.scheme() == "javascript";
|
||||||
if is_javascript {
|
if is_javascript {
|
||||||
self.eval_js_url(parent_pipeline_id, &mut load_data);
|
let window = self.documents.borrow().find_window(parent_pipeline_id);
|
||||||
|
if let Some(window) = window {
|
||||||
|
ScriptThread::eval_js_url(window.upcast::<GlobalScope>(), &mut load_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match browsing_context_id {
|
match browsing_context_id {
|
||||||
|
@ -2330,7 +2333,7 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_js_url(&self, pipeline_id: PipelineId, load_data: &mut LoadData) {
|
pub fn eval_js_url(global_scope: &GlobalScope, load_data: &mut LoadData) {
|
||||||
{
|
{
|
||||||
// Turn javascript: URL into JS code to eval, according to the steps in
|
// Turn javascript: URL into JS code to eval, according to the steps in
|
||||||
// https://html.spec.whatwg.org/multipage/#javascript-protocol
|
// https://html.spec.whatwg.org/multipage/#javascript-protocol
|
||||||
|
@ -2345,30 +2348,25 @@ impl ScriptThread {
|
||||||
let script_source = percent_decode(encoded.as_bytes()).decode_utf8_lossy();
|
let script_source = percent_decode(encoded.as_bytes()).decode_utf8_lossy();
|
||||||
|
|
||||||
// Script source is ready to be evaluated (11.)
|
// Script source is ready to be evaluated (11.)
|
||||||
let window = self.documents.borrow().find_window(pipeline_id);
|
let _ac = JSAutoCompartment::new(global_scope.get_cx(), global_scope.reflector().get_jsobject().get());
|
||||||
|
rooted!(in(global_scope.get_cx()) let mut jsval = UndefinedValue());
|
||||||
|
global_scope.evaluate_js_on_global_with_result(&script_source, jsval.handle_mut());
|
||||||
|
|
||||||
if let Some(window) = window {
|
load_data.js_eval_result = if jsval.get().is_string() {
|
||||||
let _ac = JSAutoCompartment::new(self.get_cx(), window.reflector().get_jsobject().get());
|
unsafe {
|
||||||
rooted!(in(self.get_cx()) let mut jsval = UndefinedValue());
|
let strval = DOMString::from_jsval(global_scope.get_cx(),
|
||||||
window.upcast::<GlobalScope>().evaluate_js_on_global_with_result(
|
jsval.handle(),
|
||||||
&script_source, jsval.handle_mut());
|
StringificationBehavior::Empty);
|
||||||
|
match strval {
|
||||||
load_data.js_eval_result = if jsval.get().is_string() {
|
Ok(ConversionResult::Success(s)) => {
|
||||||
unsafe {
|
Some(JsEvalResult::Ok(String::from(s).as_bytes().to_vec()))
|
||||||
let strval = DOMString::from_jsval(self.get_cx(),
|
},
|
||||||
jsval.handle(),
|
_ => None,
|
||||||
StringificationBehavior::Empty);
|
|
||||||
match strval {
|
|
||||||
Ok(ConversionResult::Success(s)) => {
|
|
||||||
Some(JsEvalResult::Ok(String::from(s).as_bytes().to_vec()))
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
Some(JsEvalResult::NoContent)
|
} else {
|
||||||
};
|
Some(JsEvalResult::NoContent)
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
load_data.url = ServoUrl::parse("about:blank").unwrap();
|
load_data.url = ServoUrl::parse("about:blank").unwrap();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue