mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
implement opener, disowning
This commit is contained in:
parent
f408b798c4
commit
21bf5a3a4b
32 changed files with 273 additions and 143 deletions
|
@ -690,6 +690,7 @@ where
|
||||||
browsing_context_id: BrowsingContextId,
|
browsing_context_id: BrowsingContextId,
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
parent_info: Option<PipelineId>,
|
parent_info: Option<PipelineId>,
|
||||||
|
opener: Option<BrowsingContextId>,
|
||||||
initial_window_size: Option<TypedSize2D<f32, CSSPixel>>,
|
initial_window_size: Option<TypedSize2D<f32, CSSPixel>>,
|
||||||
// TODO: we have to provide ownership of the LoadData
|
// TODO: we have to provide ownership of the LoadData
|
||||||
// here, because it will be send on an ipc channel,
|
// here, because it will be send on an ipc channel,
|
||||||
|
@ -764,6 +765,7 @@ where
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
parent_info,
|
parent_info,
|
||||||
|
opener,
|
||||||
script_to_constellation_chan: ScriptToConstellationChan {
|
script_to_constellation_chan: ScriptToConstellationChan {
|
||||||
sender: self.script_sender.clone(),
|
sender: self.script_sender.clone(),
|
||||||
pipeline_id: pipeline_id,
|
pipeline_id: pipeline_id,
|
||||||
|
@ -1256,6 +1258,13 @@ where
|
||||||
warn!("Sending reply to get parent info failed ({:?}).", e);
|
warn!("Sending reply to get parent info failed ({:?}).", e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
FromScriptMsg::GetTopForBrowsingContext(browsing_context_id, sender) => {
|
||||||
|
let result = self.browsing_contexts.get(&browsing_context_id)
|
||||||
|
.and_then(|bc| Some(bc.top_level_id));
|
||||||
|
if let Err(e) = sender.send(result) {
|
||||||
|
warn!("Sending reply to get top for browsing context info failed ({:?}).", e);
|
||||||
|
}
|
||||||
|
},
|
||||||
FromScriptMsg::GetChildBrowsingContextId(browsing_context_id, index, sender) => {
|
FromScriptMsg::GetChildBrowsingContextId(browsing_context_id, index, sender) => {
|
||||||
let result = self
|
let result = self
|
||||||
.browsing_contexts
|
.browsing_contexts
|
||||||
|
@ -1547,11 +1556,12 @@ where
|
||||||
(window_size, pipeline_id)
|
(window_size, pipeline_id)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (pipeline_url, parent_info) = {
|
let (pipeline_url, parent_info, opener) = {
|
||||||
let pipeline = pipeline_id.and_then(|id| self.pipelines.get(&id));
|
let pipeline = pipeline_id.and_then(|id| self.pipelines.get(&id));
|
||||||
let pipeline_url = pipeline.map(|pipeline| pipeline.url.clone());
|
let pipeline_url = pipeline.map(|pipeline| pipeline.url.clone());
|
||||||
let parent_info = pipeline.and_then(|pipeline| pipeline.parent_info);
|
let parent_info = pipeline.and_then(|pipeline| pipeline.parent_info);
|
||||||
(pipeline_url, parent_info)
|
let opener = pipeline.and_then(|pipeline| pipeline.opener);
|
||||||
|
(pipeline_url, parent_info, opener)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.close_browsing_context_children(
|
self.close_browsing_context_children(
|
||||||
|
@ -1578,6 +1588,7 @@ where
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
parent_info,
|
parent_info,
|
||||||
|
opener,
|
||||||
window_size,
|
window_size,
|
||||||
load_data.clone(),
|
load_data.clone(),
|
||||||
sandbox,
|
sandbox,
|
||||||
|
@ -1672,6 +1683,7 @@ where
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
Some(window_size),
|
Some(window_size),
|
||||||
load_data.clone(),
|
load_data.clone(),
|
||||||
sandbox,
|
sandbox,
|
||||||
|
@ -1805,6 +1817,7 @@ where
|
||||||
load_info.info.browsing_context_id,
|
load_info.info.browsing_context_id,
|
||||||
load_info.info.top_level_browsing_context_id,
|
load_info.info.top_level_browsing_context_id,
|
||||||
Some(load_info.info.parent_pipeline_id),
|
Some(load_info.info.parent_pipeline_id),
|
||||||
|
None,
|
||||||
window_size,
|
window_size,
|
||||||
load_data.clone(),
|
load_data.clone(),
|
||||||
load_info.sandbox,
|
load_info.sandbox,
|
||||||
|
@ -1850,6 +1863,7 @@ where
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
Some(parent_pipeline_id),
|
Some(parent_pipeline_id),
|
||||||
|
None,
|
||||||
script_sender,
|
script_sender,
|
||||||
layout_sender,
|
layout_sender,
|
||||||
self.compositor_proxy.clone(),
|
self.compositor_proxy.clone(),
|
||||||
|
@ -1887,8 +1901,8 @@ where
|
||||||
let load_data = LoadData::new(url.clone(), None, None, None);
|
let load_data = LoadData::new(url.clone(), None, None, None);
|
||||||
|
|
||||||
let pipeline = {
|
let pipeline = {
|
||||||
let opener_pipeline = match self.pipelines.get(&opener_pipeline_id) {
|
let (opener_pipeline, opener_id) = match self.pipelines.get(&opener_pipeline_id) {
|
||||||
Some(parent_pipeline) => parent_pipeline,
|
Some(opener_pipeline) => (opener_pipeline, opener_pipeline.browsing_context_id),
|
||||||
None => return warn!("Auxiliary loaded url in closed pipeline {}.", opener_pipeline_id),
|
None => return warn!("Auxiliary loaded url in closed pipeline {}.", opener_pipeline_id),
|
||||||
};
|
};
|
||||||
let opener_host = match reg_host(&opener_pipeline.url) {
|
let opener_host = match reg_host(&opener_pipeline.url) {
|
||||||
|
@ -1907,6 +1921,7 @@ where
|
||||||
new_browsing_context_id,
|
new_browsing_context_id,
|
||||||
new_top_level_browsing_context_id,
|
new_top_level_browsing_context_id,
|
||||||
None,
|
None,
|
||||||
|
Some(opener_id),
|
||||||
script_sender,
|
script_sender,
|
||||||
layout_sender,
|
layout_sender,
|
||||||
self.compositor_proxy.clone(),
|
self.compositor_proxy.clone(),
|
||||||
|
@ -2010,8 +2025,8 @@ where
|
||||||
// requested change so it can update its internal state.
|
// requested change so it can update its internal state.
|
||||||
//
|
//
|
||||||
// If replace is true, the current entry is replaced instead of a new entry being added.
|
// If replace is true, the current entry is replaced instead of a new entry being added.
|
||||||
let (browsing_context_id, parent_info) = match self.pipelines.get(&source_id) {
|
let (browsing_context_id, parent_info, opener) = match self.pipelines.get(&source_id) {
|
||||||
Some(pipeline) => (pipeline.browsing_context_id, pipeline.parent_info),
|
Some(pipeline) => (pipeline.browsing_context_id, pipeline.parent_info, pipeline.opener),
|
||||||
None => {
|
None => {
|
||||||
warn!("Pipeline {} loaded after closure.", source_id);
|
warn!("Pipeline {} loaded after closure.", source_id);
|
||||||
return None;
|
return None;
|
||||||
|
@ -2088,6 +2103,7 @@ where
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_id,
|
top_level_id,
|
||||||
None,
|
None,
|
||||||
|
opener,
|
||||||
window_size,
|
window_size,
|
||||||
load_data.clone(),
|
load_data.clone(),
|
||||||
sandbox,
|
sandbox,
|
||||||
|
@ -2372,19 +2388,21 @@ where
|
||||||
// TODO: Save the sandbox state so it can be restored here.
|
// TODO: Save the sandbox state so it can be restored here.
|
||||||
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
|
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
|
||||||
let new_pipeline_id = PipelineId::new();
|
let new_pipeline_id = PipelineId::new();
|
||||||
let (top_level_id, parent_info, window_size, is_private) =
|
let (top_level_id, parent_info, opener, window_size, is_private) =
|
||||||
match self.browsing_contexts.get(&browsing_context_id) {
|
match self.browsing_contexts.get(&browsing_context_id) {
|
||||||
Some(browsing_context) => {
|
Some(browsing_context) => {
|
||||||
match self.pipelines.get(&browsing_context.pipeline_id) {
|
match self.pipelines.get(&browsing_context.pipeline_id) {
|
||||||
Some(pipeline) => (
|
Some(pipeline) => (
|
||||||
browsing_context.top_level_id,
|
browsing_context.top_level_id,
|
||||||
pipeline.parent_info,
|
pipeline.parent_info,
|
||||||
|
pipeline.opener,
|
||||||
browsing_context.size,
|
browsing_context.size,
|
||||||
pipeline.is_private,
|
pipeline.is_private,
|
||||||
),
|
),
|
||||||
None => (
|
None => (
|
||||||
browsing_context.top_level_id,
|
browsing_context.top_level_id,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
browsing_context.size,
|
browsing_context.size,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
@ -2397,6 +2415,7 @@ where
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_id,
|
top_level_id,
|
||||||
parent_info,
|
parent_info,
|
||||||
|
opener,
|
||||||
window_size,
|
window_size,
|
||||||
load_data.clone(),
|
load_data.clone(),
|
||||||
sandbox,
|
sandbox,
|
||||||
|
|
|
@ -62,6 +62,8 @@ pub struct Pipeline {
|
||||||
/// TODO: move this field to `BrowsingContext`.
|
/// TODO: move this field to `BrowsingContext`.
|
||||||
pub parent_info: Option<PipelineId>,
|
pub parent_info: Option<PipelineId>,
|
||||||
|
|
||||||
|
pub opener: Option<BrowsingContextId>,
|
||||||
|
|
||||||
/// The event loop handling this pipeline.
|
/// The event loop handling this pipeline.
|
||||||
pub event_loop: Rc<EventLoop>,
|
pub event_loop: Rc<EventLoop>,
|
||||||
|
|
||||||
|
@ -119,6 +121,8 @@ pub struct InitialPipelineState {
|
||||||
/// If `None`, this is the root.
|
/// If `None`, this is the root.
|
||||||
pub parent_info: Option<PipelineId>,
|
pub parent_info: Option<PipelineId>,
|
||||||
|
|
||||||
|
pub opener: Option<BrowsingContextId>,
|
||||||
|
|
||||||
/// A channel to the associated constellation.
|
/// A channel to the associated constellation.
|
||||||
pub script_to_constellation_chan: ScriptToConstellationChan,
|
pub script_to_constellation_chan: ScriptToConstellationChan,
|
||||||
|
|
||||||
|
@ -216,6 +220,7 @@ impl Pipeline {
|
||||||
new_pipeline_id: state.id,
|
new_pipeline_id: state.id,
|
||||||
browsing_context_id: state.browsing_context_id,
|
browsing_context_id: state.browsing_context_id,
|
||||||
top_level_browsing_context_id: state.top_level_browsing_context_id,
|
top_level_browsing_context_id: state.top_level_browsing_context_id,
|
||||||
|
opener: state.opener,
|
||||||
load_data: state.load_data.clone(),
|
load_data: state.load_data.clone(),
|
||||||
window_size: window_size,
|
window_size: window_size,
|
||||||
pipeline_port: pipeline_port,
|
pipeline_port: pipeline_port,
|
||||||
|
@ -266,6 +271,7 @@ impl Pipeline {
|
||||||
browsing_context_id: state.browsing_context_id,
|
browsing_context_id: state.browsing_context_id,
|
||||||
top_level_browsing_context_id: state.top_level_browsing_context_id,
|
top_level_browsing_context_id: state.top_level_browsing_context_id,
|
||||||
parent_info: state.parent_info,
|
parent_info: state.parent_info,
|
||||||
|
opener: state.opener,
|
||||||
script_to_constellation_chan: state.script_to_constellation_chan.clone(),
|
script_to_constellation_chan: state.script_to_constellation_chan.clone(),
|
||||||
scheduler_chan: state.scheduler_chan,
|
scheduler_chan: state.scheduler_chan,
|
||||||
devtools_chan: script_to_devtools_chan,
|
devtools_chan: script_to_devtools_chan,
|
||||||
|
@ -312,6 +318,7 @@ impl Pipeline {
|
||||||
state.browsing_context_id,
|
state.browsing_context_id,
|
||||||
state.top_level_browsing_context_id,
|
state.top_level_browsing_context_id,
|
||||||
state.parent_info,
|
state.parent_info,
|
||||||
|
state.opener,
|
||||||
script_chan,
|
script_chan,
|
||||||
pipeline_chan,
|
pipeline_chan,
|
||||||
state.compositor_proxy,
|
state.compositor_proxy,
|
||||||
|
@ -329,6 +336,7 @@ impl Pipeline {
|
||||||
browsing_context_id: BrowsingContextId,
|
browsing_context_id: BrowsingContextId,
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
parent_info: Option<PipelineId>,
|
parent_info: Option<PipelineId>,
|
||||||
|
opener: Option<BrowsingContextId>,
|
||||||
event_loop: Rc<EventLoop>,
|
event_loop: Rc<EventLoop>,
|
||||||
layout_chan: IpcSender<LayoutControlMsg>,
|
layout_chan: IpcSender<LayoutControlMsg>,
|
||||||
compositor_proxy: CompositorProxy,
|
compositor_proxy: CompositorProxy,
|
||||||
|
@ -342,6 +350,7 @@ impl Pipeline {
|
||||||
browsing_context_id: browsing_context_id,
|
browsing_context_id: browsing_context_id,
|
||||||
top_level_browsing_context_id: top_level_browsing_context_id,
|
top_level_browsing_context_id: top_level_browsing_context_id,
|
||||||
parent_info: parent_info,
|
parent_info: parent_info,
|
||||||
|
opener: opener,
|
||||||
event_loop: event_loop,
|
event_loop: event_loop,
|
||||||
layout_chan: layout_chan,
|
layout_chan: layout_chan,
|
||||||
compositor_proxy: compositor_proxy,
|
compositor_proxy: compositor_proxy,
|
||||||
|
@ -469,6 +478,7 @@ pub struct UnprivilegedPipelineContent {
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
browsing_context_id: BrowsingContextId,
|
browsing_context_id: BrowsingContextId,
|
||||||
parent_info: Option<PipelineId>,
|
parent_info: Option<PipelineId>,
|
||||||
|
opener: Option<BrowsingContextId>,
|
||||||
script_to_constellation_chan: ScriptToConstellationChan,
|
script_to_constellation_chan: ScriptToConstellationChan,
|
||||||
layout_to_constellation_chan: IpcSender<LayoutMsg>,
|
layout_to_constellation_chan: IpcSender<LayoutMsg>,
|
||||||
scheduler_chan: IpcSender<TimerSchedulerMsg>,
|
scheduler_chan: IpcSender<TimerSchedulerMsg>,
|
||||||
|
@ -517,6 +527,7 @@ impl UnprivilegedPipelineContent {
|
||||||
browsing_context_id: self.browsing_context_id,
|
browsing_context_id: self.browsing_context_id,
|
||||||
top_level_browsing_context_id: self.top_level_browsing_context_id,
|
top_level_browsing_context_id: self.top_level_browsing_context_id,
|
||||||
parent_info: self.parent_info,
|
parent_info: self.parent_info,
|
||||||
|
opener: self.opener,
|
||||||
control_chan: self.script_chan.clone(),
|
control_chan: self.script_chan.clone(),
|
||||||
control_port: self.script_port,
|
control_port: self.script_port,
|
||||||
script_to_constellation_chan: self.script_to_constellation_chan.clone(),
|
script_to_constellation_chan: self.script_to_constellation_chan.clone(),
|
||||||
|
|
|
@ -177,6 +177,7 @@ impl HTMLIFrameElement {
|
||||||
new_pipeline_id: new_pipeline_id,
|
new_pipeline_id: new_pipeline_id,
|
||||||
browsing_context_id: browsing_context_id,
|
browsing_context_id: browsing_context_id,
|
||||||
top_level_browsing_context_id: top_level_browsing_context_id,
|
top_level_browsing_context_id: top_level_browsing_context_id,
|
||||||
|
opener: None,
|
||||||
load_data: load_data.unwrap(),
|
load_data: load_data.unwrap(),
|
||||||
pipeline_port: pipeline_receiver,
|
pipeline_port: pipeline_receiver,
|
||||||
content_process_shutdown_chan: None,
|
content_process_shutdown_chan: None,
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
// Note that this can return null in the case that the browsing context has been discarded.
|
// Note that this can return null in the case that the browsing context has been discarded.
|
||||||
// https://github.com/whatwg/html/issues/2115
|
// https://github.com/whatwg/html/issues/2115
|
||||||
[Unforgeable] readonly attribute WindowProxy? top;
|
[Unforgeable] readonly attribute WindowProxy? top;
|
||||||
// attribute any opener;
|
attribute any opener;
|
||||||
// Note that this can return null in the case that the browsing context has been discarded.
|
// Note that this can return null in the case that the browsing context has been discarded.
|
||||||
// https://github.com/whatwg/html/issues/2115
|
// https://github.com/whatwg/html/issues/2115
|
||||||
[Replaceable] readonly attribute WindowProxy? parent;
|
[Replaceable] readonly attribute WindowProxy? parent;
|
||||||
|
|
|
@ -61,10 +61,12 @@ use fetch;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use js::jsapi::{JSAutoCompartment, JSContext};
|
use js::jsapi::{JSAutoCompartment, JSContext};
|
||||||
use js::jsapi::{JS_GC, JS_GetRuntime};
|
use js::jsapi::{JS_GC, JS_GetRuntime, JSPROP_ENUMERATE};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::{JSVal, UndefinedValue};
|
||||||
use js::rust::HandleValue;
|
use js::rust::HandleValue;
|
||||||
|
use js::rust::wrappers::JS_DefineProperty;
|
||||||
use layout_image::fetch_image_for_layout;
|
use layout_image::fetch_image_for_layout;
|
||||||
|
use libc;
|
||||||
use microtask::MicrotaskQueue;
|
use microtask::MicrotaskQueue;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
use net_traits::{ResourceThreads, ReferrerPolicy};
|
use net_traits::{ResourceThreads, ReferrerPolicy};
|
||||||
|
@ -574,6 +576,30 @@ impl WindowMethods for Window {
|
||||||
self.window_proxy().open(url, target, features)
|
self.window_proxy().open(url, target, features)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-opener
|
||||||
|
unsafe fn Opener(&self, cx: *mut JSContext) -> JSVal {
|
||||||
|
self.window_proxy().opener(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-opener
|
||||||
|
unsafe fn SetOpener(&self, cx: *mut JSContext, value: HandleValue) {
|
||||||
|
// Step 1.
|
||||||
|
if value.is_null() {
|
||||||
|
return self.window_proxy().disown();
|
||||||
|
}
|
||||||
|
// Step 2.
|
||||||
|
let obj = self.reflector().get_jsobject();
|
||||||
|
assert!(JS_DefineProperty(cx,
|
||||||
|
obj,
|
||||||
|
"opener\0".as_ptr() as *const libc::c_char,
|
||||||
|
value,
|
||||||
|
JSPROP_ENUMERATE,
|
||||||
|
None,
|
||||||
|
None));
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-window-closed
|
// https://html.spec.whatwg.org/multipage/#dom-window-closed
|
||||||
fn Closed(&self) -> bool {
|
fn Closed(&self) -> bool {
|
||||||
self.window_proxy.get()
|
self.window_proxy.get()
|
||||||
|
|
|
@ -36,7 +36,7 @@ use js::jsapi::HandleValue as RawHandleValue;
|
||||||
use js::jsapi::MutableHandle as RawMutableHandle;
|
use js::jsapi::MutableHandle as RawMutableHandle;
|
||||||
use js::jsapi::MutableHandleObject as RawMutableHandleObject;
|
use js::jsapi::MutableHandleObject as RawMutableHandleObject;
|
||||||
use js::jsapi::MutableHandleValue as RawMutableHandleValue;
|
use js::jsapi::MutableHandleValue as RawMutableHandleValue;
|
||||||
use js::jsval::{UndefinedValue, PrivateValue};
|
use js::jsval::{JSVal, NullValue, UndefinedValue, PrivateValue};
|
||||||
use js::rust::{Handle, MutableHandle};
|
use js::rust::{Handle, MutableHandle};
|
||||||
use js::rust::get_object_class;
|
use js::rust::get_object_class;
|
||||||
use js::rust::wrappers::{NewWindowProxy, SetWindowProxy, JS_TransplantObject};
|
use js::rust::wrappers::{NewWindowProxy, SetWindowProxy, JS_TransplantObject};
|
||||||
|
@ -67,6 +67,9 @@ pub struct WindowProxy {
|
||||||
/// of the container.
|
/// of the container.
|
||||||
browsing_context_id: BrowsingContextId,
|
browsing_context_id: BrowsingContextId,
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#opener-browsing-context
|
||||||
|
opener: Option<BrowsingContextId>,
|
||||||
|
|
||||||
/// The frame id of the top-level ancestor browsing context.
|
/// The frame id of the top-level ancestor browsing context.
|
||||||
/// In the case that this is a top-level window, this is our id.
|
/// In the case that this is a top-level window, this is our id.
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
|
@ -83,6 +86,9 @@ pub struct WindowProxy {
|
||||||
/// Has the browsing context been discarded?
|
/// Has the browsing context been discarded?
|
||||||
discarded: Cell<bool>,
|
discarded: Cell<bool>,
|
||||||
|
|
||||||
|
/// Has the browsing context been disowned?
|
||||||
|
disowned: Cell<bool>,
|
||||||
|
|
||||||
/// The containing iframe element, if this is a same-origin iframe
|
/// The containing iframe element, if this is a same-origin iframe
|
||||||
frame_element: Option<Dom<Element>>,
|
frame_element: Option<Dom<Element>>,
|
||||||
|
|
||||||
|
@ -95,7 +101,8 @@ impl WindowProxy {
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
currently_active: Option<PipelineId>,
|
currently_active: Option<PipelineId>,
|
||||||
frame_element: Option<&Element>,
|
frame_element: Option<&Element>,
|
||||||
parent: Option<&WindowProxy>)
|
parent: Option<&WindowProxy>,
|
||||||
|
opener: Option<BrowsingContextId>)
|
||||||
-> WindowProxy
|
-> WindowProxy
|
||||||
{
|
{
|
||||||
let name = frame_element.map_or(DOMString::new(), |e| e.get_string_attribute(&local_name!("name")));
|
let name = frame_element.map_or(DOMString::new(), |e| e.get_string_attribute(&local_name!("name")));
|
||||||
|
@ -106,8 +113,10 @@ impl WindowProxy {
|
||||||
name: DomRefCell::new(name),
|
name: DomRefCell::new(name),
|
||||||
currently_active: Cell::new(currently_active),
|
currently_active: Cell::new(currently_active),
|
||||||
discarded: Cell::new(false),
|
discarded: Cell::new(false),
|
||||||
|
disowned: Cell::new(false),
|
||||||
frame_element: frame_element.map(Dom::from_ref),
|
frame_element: frame_element.map(Dom::from_ref),
|
||||||
parent: parent.map(Dom::from_ref),
|
parent: parent.map(Dom::from_ref),
|
||||||
|
opener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +125,8 @@ impl WindowProxy {
|
||||||
browsing_context_id: BrowsingContextId,
|
browsing_context_id: BrowsingContextId,
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
frame_element: Option<&Element>,
|
frame_element: Option<&Element>,
|
||||||
parent: Option<&WindowProxy>)
|
parent: Option<&WindowProxy>,
|
||||||
|
opener: Option<BrowsingContextId>)
|
||||||
-> DomRoot<WindowProxy>
|
-> DomRoot<WindowProxy>
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -140,7 +150,8 @@ impl WindowProxy {
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
current,
|
current,
|
||||||
frame_element,
|
frame_element,
|
||||||
parent
|
parent,
|
||||||
|
opener,
|
||||||
));
|
));
|
||||||
|
|
||||||
// The window proxy owns the browsing context.
|
// The window proxy owns the browsing context.
|
||||||
|
@ -161,7 +172,8 @@ impl WindowProxy {
|
||||||
pub fn new_dissimilar_origin(global_to_clone_from: &GlobalScope,
|
pub fn new_dissimilar_origin(global_to_clone_from: &GlobalScope,
|
||||||
browsing_context_id: BrowsingContextId,
|
browsing_context_id: BrowsingContextId,
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
parent: Option<&WindowProxy>)
|
parent: Option<&WindowProxy>,
|
||||||
|
opener: Option<BrowsingContextId>)
|
||||||
-> DomRoot<WindowProxy>
|
-> DomRoot<WindowProxy>
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -176,7 +188,8 @@ impl WindowProxy {
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
parent
|
parent,
|
||||||
|
opener
|
||||||
));
|
));
|
||||||
|
|
||||||
// Create a new dissimilar-origin window.
|
// Create a new dissimilar-origin window.
|
||||||
|
@ -205,7 +218,7 @@ impl WindowProxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#auxiliary-browsing-context
|
// https://html.spec.whatwg.org/multipage/#auxiliary-browsing-context
|
||||||
fn create_auxiliary_browsing_context(&self, name: DOMString, _noopener: bool) -> Option<DomRoot<WindowProxy>> {
|
fn create_auxiliary_browsing_context(&self, name: DOMString, noopener: bool) -> Option<DomRoot<WindowProxy>> {
|
||||||
let (chan, port) = ipc::channel().unwrap();
|
let (chan, port) = ipc::channel().unwrap();
|
||||||
let window = self.currently_active.get()
|
let window = self.currently_active.get()
|
||||||
.and_then(|id| ScriptThread::find_document(id))
|
.and_then(|id| ScriptThread::find_document(id))
|
||||||
|
@ -237,6 +250,7 @@ impl WindowProxy {
|
||||||
new_pipeline_id: new_pipeline_id,
|
new_pipeline_id: new_pipeline_id,
|
||||||
browsing_context_id: new_browsing_context_id,
|
browsing_context_id: new_browsing_context_id,
|
||||||
top_level_browsing_context_id: new_top_level_browsing_context_id,
|
top_level_browsing_context_id: new_top_level_browsing_context_id,
|
||||||
|
opener: Some(self.browsing_context_id),
|
||||||
load_data: load_data,
|
load_data: load_data,
|
||||||
pipeline_port: pipeline_receiver,
|
pipeline_port: pipeline_receiver,
|
||||||
content_process_shutdown_chan: None,
|
content_process_shutdown_chan: None,
|
||||||
|
@ -248,17 +262,64 @@ impl WindowProxy {
|
||||||
ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
|
ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
|
||||||
let msg = EmbedderMsg::BrowserCreated(new_top_level_browsing_context_id);
|
let msg = EmbedderMsg::BrowserCreated(new_top_level_browsing_context_id);
|
||||||
window.send_to_embedder(msg);
|
window.send_to_embedder(msg);
|
||||||
|
// TODO: if noopener is false, copy the sessionStorage storage area of the creator origin.
|
||||||
|
// See step 14 of https://html.spec.whatwg.org/multipage/#creating-a-new-browsing-context
|
||||||
let auxiliary = ScriptThread::find_document(new_pipeline_id).and_then(|doc| doc.browsing_context());
|
let auxiliary = ScriptThread::find_document(new_pipeline_id).and_then(|doc| doc.browsing_context());
|
||||||
if let Some(proxy) = auxiliary {
|
if let Some(proxy) = auxiliary {
|
||||||
if name.to_lowercase() != "_blank" {
|
if name.to_lowercase() != "_blank" {
|
||||||
proxy.set_name(name);
|
proxy.set_name(name);
|
||||||
}
|
}
|
||||||
|
if noopener {
|
||||||
|
proxy.disown();
|
||||||
|
}
|
||||||
return Some(proxy)
|
return Some(proxy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#disowned-its-opener
|
||||||
|
pub fn disown(&self) {
|
||||||
|
self.disowned.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-opener
|
||||||
|
pub unsafe fn opener(&self, cx: *mut JSContext) -> JSVal {
|
||||||
|
if self.disowned.get() {
|
||||||
|
return NullValue()
|
||||||
|
}
|
||||||
|
let opener_id = match self.opener {
|
||||||
|
Some(opener_browsing_context_id) => opener_browsing_context_id,
|
||||||
|
None => return NullValue()
|
||||||
|
};
|
||||||
|
let opener_proxy = match ScriptThread::find_window_proxy(opener_id) {
|
||||||
|
Some(window_proxy) => window_proxy,
|
||||||
|
None => {
|
||||||
|
let sender_pipeline_id = self.currently_active().unwrap();
|
||||||
|
match ScriptThread::get_top_level_for_browsing_context(sender_pipeline_id, opener_id) {
|
||||||
|
Some(opener_top_id) => {
|
||||||
|
let global_to_clone_from = GlobalScope::from_context(cx);
|
||||||
|
WindowProxy::new_dissimilar_origin(
|
||||||
|
&*global_to_clone_from,
|
||||||
|
opener_id,
|
||||||
|
opener_top_id,
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
)
|
||||||
|
},
|
||||||
|
None => return NullValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if opener_proxy.is_browsing_context_discarded() {
|
||||||
|
return NullValue()
|
||||||
|
}
|
||||||
|
rooted!(in(cx) let mut val = UndefinedValue());
|
||||||
|
opener_proxy.to_jsval(cx, val.handle_mut());
|
||||||
|
return val.get()
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#window-open-steps
|
// https://html.spec.whatwg.org/multipage/#window-open-steps
|
||||||
pub fn open(&self,
|
pub fn open(&self,
|
||||||
url: DOMString,
|
url: DOMString,
|
||||||
|
@ -314,7 +375,11 @@ impl WindowProxy {
|
||||||
},
|
},
|
||||||
"_parent" => {
|
"_parent" => {
|
||||||
// Step 4
|
// Step 4
|
||||||
(Some(DomRoot::from_ref(self.parent().unwrap())), false)
|
if let Some(parent) = self.parent() {
|
||||||
|
return (Some(DomRoot::from_ref(parent)), false)
|
||||||
|
}
|
||||||
|
(None, false)
|
||||||
|
|
||||||
},
|
},
|
||||||
"_top" => {
|
"_top" => {
|
||||||
// Step 5
|
// Step 5
|
||||||
|
@ -336,6 +401,10 @@ impl WindowProxy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_auxiliary(&self) -> bool {
|
||||||
|
self.opener.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn discard_browsing_context(&self) {
|
pub fn discard_browsing_context(&self) {
|
||||||
self.discarded.set(true);
|
self.discarded.set(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,8 @@ struct InProgressLoad {
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
/// The parent pipeline and frame type associated with this load, if any.
|
/// The parent pipeline and frame type associated with this load, if any.
|
||||||
parent_info: Option<PipelineId>,
|
parent_info: Option<PipelineId>,
|
||||||
|
/// The opener, if this is an auxiliary.
|
||||||
|
opener: Option<BrowsingContextId>,
|
||||||
/// The current window size associated with this pipeline.
|
/// The current window size associated with this pipeline.
|
||||||
window_size: Option<WindowSizeData>,
|
window_size: Option<WindowSizeData>,
|
||||||
/// Channel to the layout thread associated with this pipeline.
|
/// Channel to the layout thread associated with this pipeline.
|
||||||
|
@ -183,6 +185,7 @@ impl InProgressLoad {
|
||||||
browsing_context_id: BrowsingContextId,
|
browsing_context_id: BrowsingContextId,
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
parent_info: Option<PipelineId>,
|
parent_info: Option<PipelineId>,
|
||||||
|
opener: Option<BrowsingContextId>,
|
||||||
layout_chan: Sender<message::Msg>,
|
layout_chan: Sender<message::Msg>,
|
||||||
window_size: Option<WindowSizeData>,
|
window_size: Option<WindowSizeData>,
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
|
@ -195,6 +198,7 @@ impl InProgressLoad {
|
||||||
browsing_context_id: browsing_context_id,
|
browsing_context_id: browsing_context_id,
|
||||||
top_level_browsing_context_id: top_level_browsing_context_id,
|
top_level_browsing_context_id: top_level_browsing_context_id,
|
||||||
parent_info: parent_info,
|
parent_info: parent_info,
|
||||||
|
opener: opener,
|
||||||
layout_chan: layout_chan,
|
layout_chan: layout_chan,
|
||||||
window_size: window_size,
|
window_size: window_size,
|
||||||
activity: DocumentActivity::FullyActive,
|
activity: DocumentActivity::FullyActive,
|
||||||
|
@ -569,6 +573,7 @@ impl ScriptThreadFactory for ScriptThread {
|
||||||
let browsing_context_id = state.browsing_context_id;
|
let browsing_context_id = state.browsing_context_id;
|
||||||
let top_level_browsing_context_id = state.top_level_browsing_context_id;
|
let top_level_browsing_context_id = state.top_level_browsing_context_id;
|
||||||
let parent_info = state.parent_info;
|
let parent_info = state.parent_info;
|
||||||
|
let opener = state.opener;
|
||||||
let mem_profiler_chan = state.mem_profiler_chan.clone();
|
let mem_profiler_chan = state.mem_profiler_chan.clone();
|
||||||
let window_size = state.window_size;
|
let window_size = state.window_size;
|
||||||
let script_thread = ScriptThread::new(state,
|
let script_thread = ScriptThread::new(state,
|
||||||
|
@ -583,7 +588,7 @@ impl ScriptThreadFactory for ScriptThread {
|
||||||
|
|
||||||
let origin = MutableOrigin::new(load_data.url.origin());
|
let origin = MutableOrigin::new(load_data.url.origin());
|
||||||
let new_load = InProgressLoad::new(id, browsing_context_id, top_level_browsing_context_id, parent_info,
|
let new_load = InProgressLoad::new(id, browsing_context_id, top_level_browsing_context_id, parent_info,
|
||||||
layout_chan, window_size, load_data.url.clone(), origin);
|
opener, layout_chan, window_size, load_data.url.clone(), origin);
|
||||||
script_thread.pre_page_load(new_load, load_data);
|
script_thread.pre_page_load(new_load, load_data);
|
||||||
|
|
||||||
let reporter_name = format!("script-reporter-{}", id);
|
let reporter_name = format!("script-reporter-{}", id);
|
||||||
|
@ -706,6 +711,15 @@ impl ScriptThread {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_top_level_for_browsing_context(sender_pipeline: PipelineId,
|
||||||
|
browsing_context_id: BrowsingContextId)
|
||||||
|
-> Option<TopLevelBrowsingContextId> {
|
||||||
|
SCRIPT_THREAD_ROOT.with(|root| root.get().and_then(|script_thread| {
|
||||||
|
let script_thread = unsafe { &*script_thread };
|
||||||
|
script_thread.ask_constellation_for_top_level_info(sender_pipeline, browsing_context_id)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn find_document(id: PipelineId) -> Option<DomRoot<Document>> {
|
pub fn find_document(id: PipelineId) -> Option<DomRoot<Document>> {
|
||||||
SCRIPT_THREAD_ROOT.with(|root| root.get().and_then(|script_thread| {
|
SCRIPT_THREAD_ROOT.with(|root| root.get().and_then(|script_thread| {
|
||||||
let script_thread = unsafe { &*script_thread };
|
let script_thread = unsafe { &*script_thread };
|
||||||
|
@ -1553,6 +1567,7 @@ impl ScriptThread {
|
||||||
new_pipeline_id,
|
new_pipeline_id,
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
|
opener,
|
||||||
load_data,
|
load_data,
|
||||||
window_size,
|
window_size,
|
||||||
pipeline_port,
|
pipeline_port,
|
||||||
|
@ -1597,6 +1612,7 @@ impl ScriptThread {
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
parent_info,
|
parent_info,
|
||||||
|
opener,
|
||||||
layout_chan,
|
layout_chan,
|
||||||
window_size,
|
window_size,
|
||||||
load_data.url.clone(),
|
load_data.url.clone(),
|
||||||
|
@ -2025,6 +2041,16 @@ impl ScriptThread {
|
||||||
result_receiver.recv().expect("Failed to get frame id from constellation.")
|
result_receiver.recv().expect("Failed to get frame id from constellation.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ask_constellation_for_top_level_info(&self,
|
||||||
|
sender_pipeline: PipelineId,
|
||||||
|
browsing_context_id: BrowsingContextId)
|
||||||
|
-> Option<TopLevelBrowsingContextId> {
|
||||||
|
let (result_sender, result_receiver) = ipc::channel().unwrap();
|
||||||
|
let msg = ScriptMsg::GetTopForBrowsingContext(browsing_context_id, result_sender);
|
||||||
|
self.script_sender.send((sender_pipeline, msg)).expect("Failed to send to constellation.");
|
||||||
|
result_receiver.recv().expect("Failed to get top-level id from constellation.")
|
||||||
|
}
|
||||||
|
|
||||||
// Get the browsing context for a pipeline that may exist in another
|
// Get the browsing context for a pipeline that may exist in another
|
||||||
// script thread. If the browsing context already exists in the
|
// script thread. If the browsing context already exists in the
|
||||||
// `window_proxies` map, we return it, otherwise we recursively
|
// `window_proxies` map, we return it, otherwise we recursively
|
||||||
|
@ -2034,7 +2060,8 @@ impl ScriptThread {
|
||||||
fn remote_window_proxy(&self,
|
fn remote_window_proxy(&self,
|
||||||
global_to_clone: &GlobalScope,
|
global_to_clone: &GlobalScope,
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
pipeline_id: PipelineId)
|
pipeline_id: PipelineId,
|
||||||
|
opener: Option<BrowsingContextId>)
|
||||||
-> Option<DomRoot<WindowProxy>>
|
-> Option<DomRoot<WindowProxy>>
|
||||||
{
|
{
|
||||||
let browsing_context_id = self.ask_constellation_for_browsing_context_id(pipeline_id)?;
|
let browsing_context_id = self.ask_constellation_for_browsing_context_id(pipeline_id)?;
|
||||||
|
@ -2042,12 +2069,13 @@ impl ScriptThread {
|
||||||
return Some(DomRoot::from_ref(window_proxy));
|
return Some(DomRoot::from_ref(window_proxy));
|
||||||
}
|
}
|
||||||
let parent = self.ask_constellation_for_parent_info(pipeline_id).and_then(|parent_id| {
|
let parent = self.ask_constellation_for_parent_info(pipeline_id).and_then(|parent_id| {
|
||||||
self.remote_window_proxy(global_to_clone, top_level_browsing_context_id, parent_id)
|
self.remote_window_proxy(global_to_clone, top_level_browsing_context_id, parent_id, opener)
|
||||||
});
|
});
|
||||||
let window_proxy = WindowProxy::new_dissimilar_origin(global_to_clone,
|
let window_proxy = WindowProxy::new_dissimilar_origin(global_to_clone,
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
parent.r());
|
parent.r(),
|
||||||
|
opener);
|
||||||
self.window_proxies.borrow_mut().insert(browsing_context_id, Dom::from_ref(&*window_proxy));
|
self.window_proxies.borrow_mut().insert(browsing_context_id, Dom::from_ref(&*window_proxy));
|
||||||
Some(window_proxy)
|
Some(window_proxy)
|
||||||
}
|
}
|
||||||
|
@ -2062,7 +2090,8 @@ impl ScriptThread {
|
||||||
window: &Window,
|
window: &Window,
|
||||||
browsing_context_id: BrowsingContextId,
|
browsing_context_id: BrowsingContextId,
|
||||||
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
parent_info: Option<PipelineId>)
|
parent_info: Option<PipelineId>,
|
||||||
|
opener: Option<BrowsingContextId>)
|
||||||
-> DomRoot<WindowProxy>
|
-> DomRoot<WindowProxy>
|
||||||
{
|
{
|
||||||
if let Some(window_proxy) = self.window_proxies.borrow().get(&browsing_context_id) {
|
if let Some(window_proxy) = self.window_proxies.borrow().get(&browsing_context_id) {
|
||||||
|
@ -2075,15 +2104,17 @@ impl ScriptThread {
|
||||||
let parent = match (parent_info, iframe.as_ref()) {
|
let parent = match (parent_info, iframe.as_ref()) {
|
||||||
(_, Some(iframe)) => Some(window_from_node(&**iframe).window_proxy()),
|
(_, Some(iframe)) => Some(window_from_node(&**iframe).window_proxy()),
|
||||||
(Some(parent_id), _) => self.remote_window_proxy(window.upcast(),
|
(Some(parent_id), _) => self.remote_window_proxy(window.upcast(),
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
parent_id),
|
parent_id,
|
||||||
|
opener),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let window_proxy = WindowProxy::new(&window,
|
let window_proxy = WindowProxy::new(&window,
|
||||||
browsing_context_id,
|
browsing_context_id,
|
||||||
top_level_browsing_context_id,
|
top_level_browsing_context_id,
|
||||||
iframe.r().map(Castable::upcast),
|
iframe.r().map(Castable::upcast),
|
||||||
parent.r());
|
parent.r(),
|
||||||
|
opener);
|
||||||
self.window_proxies.borrow_mut().insert(browsing_context_id, Dom::from_ref(&*window_proxy));
|
self.window_proxies.borrow_mut().insert(browsing_context_id, Dom::from_ref(&*window_proxy));
|
||||||
window_proxy
|
window_proxy
|
||||||
}
|
}
|
||||||
|
@ -2162,7 +2193,8 @@ impl ScriptThread {
|
||||||
let window_proxy = self.local_window_proxy(&window,
|
let window_proxy = self.local_window_proxy(&window,
|
||||||
incomplete.browsing_context_id,
|
incomplete.browsing_context_id,
|
||||||
incomplete.top_level_browsing_context_id,
|
incomplete.top_level_browsing_context_id,
|
||||||
incomplete.parent_info);
|
incomplete.parent_info,
|
||||||
|
incomplete.opener);
|
||||||
window.init_window_proxy(&window_proxy);
|
window.init_window_proxy(&window_proxy);
|
||||||
|
|
||||||
let last_modified = metadata.headers.as_ref().and_then(|headers| {
|
let last_modified = metadata.headers.as_ref().and_then(|headers| {
|
||||||
|
|
|
@ -193,6 +193,8 @@ pub struct NewLayoutInfo {
|
||||||
pub browsing_context_id: BrowsingContextId,
|
pub browsing_context_id: BrowsingContextId,
|
||||||
/// Id of the top-level browsing context associated with this pipeline.
|
/// Id of the top-level browsing context associated with this pipeline.
|
||||||
pub top_level_browsing_context_id: TopLevelBrowsingContextId,
|
pub top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
|
/// Id of the opener, if any
|
||||||
|
pub opener: Option<BrowsingContextId>,
|
||||||
/// Network request data which will be initiated by the script thread.
|
/// Network request data which will be initiated by the script thread.
|
||||||
pub load_data: LoadData,
|
pub load_data: LoadData,
|
||||||
/// Information about the initial window size.
|
/// Information about the initial window size.
|
||||||
|
@ -521,6 +523,8 @@ pub struct InitialScriptState {
|
||||||
pub browsing_context_id: BrowsingContextId,
|
pub browsing_context_id: BrowsingContextId,
|
||||||
/// The ID of the top-level browsing context this script is part of.
|
/// The ID of the top-level browsing context this script is part of.
|
||||||
pub top_level_browsing_context_id: TopLevelBrowsingContextId,
|
pub top_level_browsing_context_id: TopLevelBrowsingContextId,
|
||||||
|
/// The ID of the opener, if any.
|
||||||
|
pub opener: Option<BrowsingContextId>,
|
||||||
/// A channel with which messages can be sent to us (the script thread).
|
/// A channel with which messages can be sent to us (the script thread).
|
||||||
pub control_chan: IpcSender<ConstellationControlMsg>,
|
pub control_chan: IpcSender<ConstellationControlMsg>,
|
||||||
/// A port on which messages sent by the constellation to script can be received.
|
/// A port on which messages sent by the constellation to script can be received.
|
||||||
|
|
|
@ -17,7 +17,8 @@ use embedder_traits::EmbedderMsg;
|
||||||
use euclid::{Size2D, TypedSize2D};
|
use euclid::{Size2D, TypedSize2D};
|
||||||
use gfx_traits::Epoch;
|
use gfx_traits::Epoch;
|
||||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||||
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId, TraversalDirection};
|
use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId};
|
||||||
|
use msg::constellation_msg::{HistoryStateId, TraversalDirection};
|
||||||
use net_traits::CoreResourceMsg;
|
use net_traits::CoreResourceMsg;
|
||||||
use net_traits::request::RequestInit;
|
use net_traits::request::RequestInit;
|
||||||
use net_traits::storage_thread::StorageType;
|
use net_traits::storage_thread::StorageType;
|
||||||
|
@ -105,6 +106,8 @@ pub enum ScriptMsg {
|
||||||
GetBrowsingContextId(PipelineId, IpcSender<Option<BrowsingContextId>>),
|
GetBrowsingContextId(PipelineId, IpcSender<Option<BrowsingContextId>>),
|
||||||
/// Get the parent info for a given pipeline.
|
/// Get the parent info for a given pipeline.
|
||||||
GetParentInfo(PipelineId, IpcSender<Option<PipelineId>>),
|
GetParentInfo(PipelineId, IpcSender<Option<PipelineId>>),
|
||||||
|
/// Get the top-level browsing context info for a given browsing context.
|
||||||
|
GetTopForBrowsingContext(BrowsingContextId, IpcSender<Option<TopLevelBrowsingContextId>>),
|
||||||
/// Get the nth child browsing context ID for a given browsing context, sorted in tree order.
|
/// Get the nth child browsing context ID for a given browsing context, sorted in tree order.
|
||||||
GetChildBrowsingContextId(BrowsingContextId, usize, IpcSender<Option<BrowsingContextId>>),
|
GetChildBrowsingContextId(BrowsingContextId, usize, IpcSender<Option<BrowsingContextId>>),
|
||||||
/// All pending loads are complete, and the `load` event for this pipeline
|
/// All pending loads are complete, and the `load` event for this pipeline
|
||||||
|
@ -184,6 +187,7 @@ impl fmt::Debug for ScriptMsg {
|
||||||
GetClipboardContents(..) => "GetClipboardContents",
|
GetClipboardContents(..) => "GetClipboardContents",
|
||||||
GetBrowsingContextId(..) => "GetBrowsingContextId",
|
GetBrowsingContextId(..) => "GetBrowsingContextId",
|
||||||
GetParentInfo(..) => "GetParentInfo",
|
GetParentInfo(..) => "GetParentInfo",
|
||||||
|
GetTopForBrowsingContext(..) => "GetParentBrowsingContext",
|
||||||
GetChildBrowsingContextId(..) => "GetChildBrowsingContextId",
|
GetChildBrowsingContextId(..) => "GetChildBrowsingContextId",
|
||||||
LoadComplete => "LoadComplete",
|
LoadComplete => "LoadComplete",
|
||||||
LoadUrl(..) => "LoadUrl",
|
LoadUrl(..) => "LoadUrl",
|
||||||
|
|
|
@ -279733,6 +279733,11 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"html/browsers/windows/auxiliary-browsing-contexts/resources/opener-setter.html": [
|
||||||
|
[
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"html/browsers/windows/browsing-context-names/resources/choose-_parent-001-iframe-1.html": [
|
"html/browsers/windows/browsing-context-names/resources/choose-_parent-001-iframe-1.html": [
|
||||||
[
|
[
|
||||||
{}
|
{}
|
||||||
|
@ -352032,6 +352037,12 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"html/browsers/windows/auxiliary-browsing-contexts/opener-setter.html": [
|
||||||
|
[
|
||||||
|
"/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.html",
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.js": [
|
"html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.js": [
|
||||||
[
|
[
|
||||||
"/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.html",
|
"/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.html",
|
||||||
|
@ -587647,6 +587658,10 @@
|
||||||
"f82aa6f0abe0d16a8b132e531d165988af0af99f",
|
"f82aa6f0abe0d16a8b132e531d165988af0af99f",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
|
"html/browsers/windows/auxiliary-browsing-contexts/opener-setter.html": [
|
||||||
|
"85c52e0b42e19bdd78dda120320d66ddbb2103b4",
|
||||||
|
"testharness"
|
||||||
|
],
|
||||||
"html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.js": [
|
"html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.js": [
|
||||||
"6d540ce97c94bff5845023098d0960d51dad62b4",
|
"6d540ce97c94bff5845023098d0960d51dad62b4",
|
||||||
"testharness"
|
"testharness"
|
||||||
|
@ -587675,6 +587690,10 @@
|
||||||
"6f43a5188c790577c4a1a03da270317eedba0fb0",
|
"6f43a5188c790577c4a1a03da270317eedba0fb0",
|
||||||
"support"
|
"support"
|
||||||
],
|
],
|
||||||
|
"html/browsers/windows/auxiliary-browsing-contexts/resources/opener-setter.html": [
|
||||||
|
"4112dae0cee66138a309b202a8d09d6b256c6d4d",
|
||||||
|
"support"
|
||||||
|
],
|
||||||
"html/browsers/windows/browsing-context-names/choose-_blank-001.html": [
|
"html/browsers/windows/browsing-context-names/choose-_blank-001.html": [
|
||||||
"a1416f2eb8437a8824a26a0e2e6aa6fdede37ffa",
|
"a1416f2eb8437a8824a26a0e2e6aa6fdede37ffa",
|
||||||
"testharness"
|
"testharness"
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
[005.html]
|
||||||
|
type: testharness
|
||||||
|
expected: ERROR
|
|
@ -2,4 +2,3 @@
|
||||||
type: testharness
|
type: testharness
|
||||||
[Link with onclick javascript url and href navigation ]
|
[Link with onclick javascript url and href navigation ]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[opener-closed.html]
|
[opener-closed.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
expected: CRASH
|
||||||
[An auxiliary browsing context should report `null` for `window.opener` when that browsing context is discarded]
|
[An auxiliary browsing context should report `null` for `window.opener` when that browsing context is discarded]
|
||||||
expected: TIMEOUT
|
expected: CRASH
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[opener-multiple.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[An auxiliary browsing context should be able to open another auxiliary browsing context]
|
|
||||||
expected: TIMEOUT
|
|
|
@ -1,6 +0,0 @@
|
||||||
[opener-noreferrer.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[Auxiliary browsing context created with `rel="noreferrer"` should report `window.opener` `null`]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
[opener-setter.window.html]
|
|
||||||
[Setting window.opener to undefined]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Setting window.opener to 42]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Setting window.opener to function () { return "hi" }]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Setting window.opener to hi]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Setting window.opener to [object Object\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Setting window.opener to ]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Setting window.opener to Symbol()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
[opener.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[Newly-created auxiliary browsing context should report `window.opener`]
|
|
||||||
expected: TIMEOUT
|
|
||||||
[Browsing context created with `window.open` should report `window.opener`]
|
|
||||||
expected: FAIL
|
|
|
@ -1,8 +0,0 @@
|
||||||
[choose-_blank-001.html]
|
|
||||||
type: testharness
|
|
||||||
[window.open into `_blank` should create a new browsing context each time]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[`_blank` should be ASCII case-insensitive]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[choose-_blank-002.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[Context for opened noreferrer link targeted to "_blank" should not have opener reference]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[choose-_blank-003.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[Context created by link targeting "_blank" should retain opener reference]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[choose-_parent-001.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[The parent browsing context must be chosen if the given name is `_parent`]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[choose-_parent-002.html]
|
|
||||||
type: testharness
|
|
||||||
expected: ERROR
|
|
||||||
[choosing _parent context: multiple nested contexts]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[choose-_parent-003.html]
|
|
||||||
type: testharness
|
|
||||||
expected: ERROR
|
|
||||||
[_parent should reuse window.parent context]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[choose-_parent-004.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[choosing _parent context should be case-insensitive]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[choose-_self-002.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[choosing _self context should be case-insensitive]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[choose-_top-001.html]
|
|
||||||
type: testharness
|
|
||||||
[Should choose current browsing context for "_top" if current is top]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[choose-_top-002.html]
|
|
||||||
type: testharness
|
|
||||||
[Should choose top browsing context for "_top" if current is not top]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[choose-_top-003.html]
|
|
||||||
type: testharness
|
|
||||||
[choosing _top context should be case-insensitive]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[noreferrer-null-opener.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[rel=noreferrer nullifies window.opener]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
[targeting-cross-origin-nested-browsing-contexts.html]
|
[targeting-cross-origin-nested-browsing-contexts.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[Targeting nested browsing contexts]
|
[Targeting nested browsing contexts]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Auxiliary Browing Contexts: window.opener setter</title>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="/common/PrefixedLocalStorage.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
var prefixedLocalStorage;
|
||||||
|
setup(() => prefixedLocalStorage = new PrefixedLocalStorageTest());
|
||||||
|
async_test(t => {
|
||||||
|
t.add_cleanup(() => prefixedLocalStorage.cleanup());
|
||||||
|
prefixedLocalStorage.onSet('openerIsNull', t.step_func_done(e => {
|
||||||
|
assert_equals(e.newValue, 'true');
|
||||||
|
}));
|
||||||
|
window.open(prefixedLocalStorage.url('resources/opener-setter.html'),
|
||||||
|
'iShouldSetOpenerToNull');
|
||||||
|
}, 'Auxiliary browsing context created via `window.open` and setting `window.opener` to `null` should report `window.opener` `null`');
|
||||||
|
async_test(t => {
|
||||||
|
t.add_cleanup(() => prefixedLocalStorage.cleanup());
|
||||||
|
prefixedLocalStorage.onSet('openerIsTest', t.step_func_done(e => {
|
||||||
|
assert_equals(e.newValue, 'true');
|
||||||
|
}));
|
||||||
|
window.open(prefixedLocalStorage.url('resources/opener-setter.html'),
|
||||||
|
'iShouldSetOpenerToTest');
|
||||||
|
}, 'Auxiliary browsing context created via `window.open` and setting `window.opener` to `test` should report `test`');
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<html>
|
||||||
|
<p>This window should set the window.opener attribute</p>
|
||||||
|
<script src="/common/PrefixedLocalStorage.js"></script>
|
||||||
|
<script>
|
||||||
|
var prefixedLocalStorage = new PrefixedLocalStorageResource({
|
||||||
|
close_on_cleanup: true
|
||||||
|
});
|
||||||
|
function checkOpener () {
|
||||||
|
if (window.name == 'iShouldSetOpenerToNull') {
|
||||||
|
window.opener = null;
|
||||||
|
return prefixedLocalStorage.setItem('openerIsNull', window.opener === null);
|
||||||
|
}
|
||||||
|
if (window.name == 'iShouldSetOpenerToTest') {
|
||||||
|
window.opener = 'test';
|
||||||
|
return prefixedLocalStorage.setItem('openerIsTest', window.opener === "test");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload="checkOpener()">
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue