aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/constellation/constellation.rs33
-rw-r--r--components/constellation/pipeline.rs11
-rw-r--r--components/script/dom/htmliframeelement.rs1
-rw-r--r--components/script/dom/webidls/Window.webidl2
-rw-r--r--components/script/dom/window.rs30
-rw-r--r--components/script/dom/windowproxy.rs85
-rw-r--r--components/script/script_thread.rs50
-rw-r--r--components/script_traits/lib.rs4
-rw-r--r--components/script_traits/script_msg.rs6
-rw-r--r--tests/wpt/metadata/MANIFEST.json19
-rw-r--r--tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/005.html.ini3
-rw-r--r--tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/007.html.ini1
-rw-r--r--tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-closed.html.ini4
-rw-r--r--tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-multiple.html.ini5
-rw-r--r--tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-noreferrer.html.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.js.ini22
-rw-r--r--tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener.html.ini7
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-001.html.ini8
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-002.html.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-003.html.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-001.html.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-002.html.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-003.html.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-004.html.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_self-002.html.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-001.html.ini5
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-002.html.ini5
-rw-r--r--tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-003.html.ini5
-rw-r--r--tests/wpt/metadata/html/browsers/windows/noreferrer-null-opener.html.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/windows/targeting-cross-origin-nested-browsing-contexts.html.ini1
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.html32
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/resources/opener-setter.html23
32 files changed, 273 insertions, 143 deletions
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index f03643bdbd5..6e1e2b87f30 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -690,6 +690,7 @@ where
browsing_context_id: BrowsingContextId,
top_level_browsing_context_id: TopLevelBrowsingContextId,
parent_info: Option<PipelineId>,
+ opener: Option<BrowsingContextId>,
initial_window_size: Option<TypedSize2D<f32, CSSPixel>>,
// TODO: we have to provide ownership of the LoadData
// here, because it will be send on an ipc channel,
@@ -764,6 +765,7 @@ where
browsing_context_id,
top_level_browsing_context_id,
parent_info,
+ opener,
script_to_constellation_chan: ScriptToConstellationChan {
sender: self.script_sender.clone(),
pipeline_id: pipeline_id,
@@ -1256,6 +1258,13 @@ where
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) => {
let result = self
.browsing_contexts
@@ -1547,11 +1556,12 @@ where
(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_url = pipeline.map(|pipeline| pipeline.url.clone());
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(
@@ -1578,6 +1588,7 @@ where
browsing_context_id,
top_level_browsing_context_id,
parent_info,
+ opener,
window_size,
load_data.clone(),
sandbox,
@@ -1672,6 +1683,7 @@ where
browsing_context_id,
top_level_browsing_context_id,
None,
+ None,
Some(window_size),
load_data.clone(),
sandbox,
@@ -1805,6 +1817,7 @@ where
load_info.info.browsing_context_id,
load_info.info.top_level_browsing_context_id,
Some(load_info.info.parent_pipeline_id),
+ None,
window_size,
load_data.clone(),
load_info.sandbox,
@@ -1850,6 +1863,7 @@ where
browsing_context_id,
top_level_browsing_context_id,
Some(parent_pipeline_id),
+ None,
script_sender,
layout_sender,
self.compositor_proxy.clone(),
@@ -1887,8 +1901,8 @@ where
let load_data = LoadData::new(url.clone(), None, None, None);
let pipeline = {
- let opener_pipeline = match self.pipelines.get(&opener_pipeline_id) {
- Some(parent_pipeline) => parent_pipeline,
+ let (opener_pipeline, opener_id) = match self.pipelines.get(&opener_pipeline_id) {
+ Some(opener_pipeline) => (opener_pipeline, opener_pipeline.browsing_context_id),
None => return warn!("Auxiliary loaded url in closed pipeline {}.", opener_pipeline_id),
};
let opener_host = match reg_host(&opener_pipeline.url) {
@@ -1907,6 +1921,7 @@ where
new_browsing_context_id,
new_top_level_browsing_context_id,
None,
+ Some(opener_id),
script_sender,
layout_sender,
self.compositor_proxy.clone(),
@@ -2010,8 +2025,8 @@ where
// 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.
- let (browsing_context_id, parent_info) = match self.pipelines.get(&source_id) {
- Some(pipeline) => (pipeline.browsing_context_id, pipeline.parent_info),
+ let (browsing_context_id, parent_info, opener) = match self.pipelines.get(&source_id) {
+ Some(pipeline) => (pipeline.browsing_context_id, pipeline.parent_info, pipeline.opener),
None => {
warn!("Pipeline {} loaded after closure.", source_id);
return None;
@@ -2088,6 +2103,7 @@ where
browsing_context_id,
top_level_id,
None,
+ opener,
window_size,
load_data.clone(),
sandbox,
@@ -2372,19 +2388,21 @@ where
// TODO: Save the sandbox state so it can be restored here.
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
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) {
Some(browsing_context) => {
match self.pipelines.get(&browsing_context.pipeline_id) {
Some(pipeline) => (
browsing_context.top_level_id,
pipeline.parent_info,
+ pipeline.opener,
browsing_context.size,
pipeline.is_private,
),
None => (
browsing_context.top_level_id,
None,
+ None,
browsing_context.size,
false,
),
@@ -2397,6 +2415,7 @@ where
browsing_context_id,
top_level_id,
parent_info,
+ opener,
window_size,
load_data.clone(),
sandbox,
diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs
index 50d2911a535..62899328ca1 100644
--- a/components/constellation/pipeline.rs
+++ b/components/constellation/pipeline.rs
@@ -62,6 +62,8 @@ pub struct Pipeline {
/// TODO: move this field to `BrowsingContext`.
pub parent_info: Option<PipelineId>,
+ pub opener: Option<BrowsingContextId>,
+
/// The event loop handling this pipeline.
pub event_loop: Rc<EventLoop>,
@@ -119,6 +121,8 @@ pub struct InitialPipelineState {
/// If `None`, this is the root.
pub parent_info: Option<PipelineId>,
+ pub opener: Option<BrowsingContextId>,
+
/// A channel to the associated constellation.
pub script_to_constellation_chan: ScriptToConstellationChan,
@@ -216,6 +220,7 @@ impl Pipeline {
new_pipeline_id: state.id,
browsing_context_id: state.browsing_context_id,
top_level_browsing_context_id: state.top_level_browsing_context_id,
+ opener: state.opener,
load_data: state.load_data.clone(),
window_size: window_size,
pipeline_port: pipeline_port,
@@ -266,6 +271,7 @@ impl Pipeline {
browsing_context_id: state.browsing_context_id,
top_level_browsing_context_id: state.top_level_browsing_context_id,
parent_info: state.parent_info,
+ opener: state.opener,
script_to_constellation_chan: state.script_to_constellation_chan.clone(),
scheduler_chan: state.scheduler_chan,
devtools_chan: script_to_devtools_chan,
@@ -312,6 +318,7 @@ impl Pipeline {
state.browsing_context_id,
state.top_level_browsing_context_id,
state.parent_info,
+ state.opener,
script_chan,
pipeline_chan,
state.compositor_proxy,
@@ -329,6 +336,7 @@ impl Pipeline {
browsing_context_id: BrowsingContextId,
top_level_browsing_context_id: TopLevelBrowsingContextId,
parent_info: Option<PipelineId>,
+ opener: Option<BrowsingContextId>,
event_loop: Rc<EventLoop>,
layout_chan: IpcSender<LayoutControlMsg>,
compositor_proxy: CompositorProxy,
@@ -342,6 +350,7 @@ impl Pipeline {
browsing_context_id: browsing_context_id,
top_level_browsing_context_id: top_level_browsing_context_id,
parent_info: parent_info,
+ opener: opener,
event_loop: event_loop,
layout_chan: layout_chan,
compositor_proxy: compositor_proxy,
@@ -469,6 +478,7 @@ pub struct UnprivilegedPipelineContent {
top_level_browsing_context_id: TopLevelBrowsingContextId,
browsing_context_id: BrowsingContextId,
parent_info: Option<PipelineId>,
+ opener: Option<BrowsingContextId>,
script_to_constellation_chan: ScriptToConstellationChan,
layout_to_constellation_chan: IpcSender<LayoutMsg>,
scheduler_chan: IpcSender<TimerSchedulerMsg>,
@@ -517,6 +527,7 @@ impl UnprivilegedPipelineContent {
browsing_context_id: self.browsing_context_id,
top_level_browsing_context_id: self.top_level_browsing_context_id,
parent_info: self.parent_info,
+ opener: self.opener,
control_chan: self.script_chan.clone(),
control_port: self.script_port,
script_to_constellation_chan: self.script_to_constellation_chan.clone(),
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index 373aa9c254f..b7540344c6a 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -177,6 +177,7 @@ impl HTMLIFrameElement {
new_pipeline_id: new_pipeline_id,
browsing_context_id: browsing_context_id,
top_level_browsing_context_id: top_level_browsing_context_id,
+ opener: None,
load_data: load_data.unwrap(),
pipeline_port: pipeline_receiver,
content_process_shutdown_chan: None,
diff --git a/components/script/dom/webidls/Window.webidl b/components/script/dom/webidls/Window.webidl
index c143ec56bbf..396bb936d71 100644
--- a/components/script/dom/webidls/Window.webidl
+++ b/components/script/dom/webidls/Window.webidl
@@ -35,7 +35,7 @@
// Note that this can return null in the case that the browsing context has been discarded.
// https://github.com/whatwg/html/issues/2115
[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.
// https://github.com/whatwg/html/issues/2115
[Replaceable] readonly attribute WindowProxy? parent;
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 41b7441c3bf..b4c99ddfc94 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -61,10 +61,12 @@ use fetch;
use ipc_channel::ipc::IpcSender;
use ipc_channel::router::ROUTER;
use js::jsapi::{JSAutoCompartment, JSContext};
-use js::jsapi::{JS_GC, JS_GetRuntime};
-use js::jsval::UndefinedValue;
+use js::jsapi::{JS_GC, JS_GetRuntime, JSPROP_ENUMERATE};
+use js::jsval::{JSVal, UndefinedValue};
use js::rust::HandleValue;
+use js::rust::wrappers::JS_DefineProperty;
use layout_image::fetch_image_for_layout;
+use libc;
use microtask::MicrotaskQueue;
use msg::constellation_msg::PipelineId;
use net_traits::{ResourceThreads, ReferrerPolicy};
@@ -574,6 +576,30 @@ impl WindowMethods for Window {
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
fn Closed(&self) -> bool {
self.window_proxy.get()
diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs
index 10c925cb28d..093ea29b3d7 100644
--- a/components/script/dom/windowproxy.rs
+++ b/components/script/dom/windowproxy.rs
@@ -36,7 +36,7 @@ use js::jsapi::HandleValue as RawHandleValue;
use js::jsapi::MutableHandle as RawMutableHandle;
use js::jsapi::MutableHandleObject as RawMutableHandleObject;
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::get_object_class;
use js::rust::wrappers::{NewWindowProxy, SetWindowProxy, JS_TransplantObject};
@@ -67,6 +67,9 @@ pub struct WindowProxy {
/// of the container.
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.
/// In the case that this is a top-level window, this is our id.
top_level_browsing_context_id: TopLevelBrowsingContextId,
@@ -83,6 +86,9 @@ pub struct WindowProxy {
/// Has the browsing context been discarded?
discarded: Cell<bool>,
+ /// Has the browsing context been disowned?
+ disowned: Cell<bool>,
+
/// The containing iframe element, if this is a same-origin iframe
frame_element: Option<Dom<Element>>,
@@ -95,7 +101,8 @@ impl WindowProxy {
top_level_browsing_context_id: TopLevelBrowsingContextId,
currently_active: Option<PipelineId>,
frame_element: Option<&Element>,
- parent: Option<&WindowProxy>)
+ parent: Option<&WindowProxy>,
+ opener: Option<BrowsingContextId>)
-> WindowProxy
{
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),
currently_active: Cell::new(currently_active),
discarded: Cell::new(false),
+ disowned: Cell::new(false),
frame_element: frame_element.map(Dom::from_ref),
parent: parent.map(Dom::from_ref),
+ opener,
}
}
@@ -116,7 +125,8 @@ impl WindowProxy {
browsing_context_id: BrowsingContextId,
top_level_browsing_context_id: TopLevelBrowsingContextId,
frame_element: Option<&Element>,
- parent: Option<&WindowProxy>)
+ parent: Option<&WindowProxy>,
+ opener: Option<BrowsingContextId>)
-> DomRoot<WindowProxy>
{
unsafe {
@@ -140,7 +150,8 @@ impl WindowProxy {
top_level_browsing_context_id,
current,
frame_element,
- parent
+ parent,
+ opener,
));
// The window proxy owns the browsing context.
@@ -161,7 +172,8 @@ impl WindowProxy {
pub fn new_dissimilar_origin(global_to_clone_from: &GlobalScope,
browsing_context_id: BrowsingContextId,
top_level_browsing_context_id: TopLevelBrowsingContextId,
- parent: Option<&WindowProxy>)
+ parent: Option<&WindowProxy>,
+ opener: Option<BrowsingContextId>)
-> DomRoot<WindowProxy>
{
unsafe {
@@ -176,7 +188,8 @@ impl WindowProxy {
top_level_browsing_context_id,
None,
None,
- parent
+ parent,
+ opener
));
// Create a new dissimilar-origin window.
@@ -205,7 +218,7 @@ impl WindowProxy {
}
// 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 window = self.currently_active.get()
.and_then(|id| ScriptThread::find_document(id))
@@ -237,6 +250,7 @@ impl WindowProxy {
new_pipeline_id: new_pipeline_id,
browsing_context_id: new_browsing_context_id,
top_level_browsing_context_id: new_top_level_browsing_context_id,
+ opener: Some(self.browsing_context_id),
load_data: load_data,
pipeline_port: pipeline_receiver,
content_process_shutdown_chan: None,
@@ -248,17 +262,64 @@ impl WindowProxy {
ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
let msg = EmbedderMsg::BrowserCreated(new_top_level_browsing_context_id);
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());
if let Some(proxy) = auxiliary {
if name.to_lowercase() != "_blank" {
proxy.set_name(name);
}
+ if noopener {
+ proxy.disown();
+ }
return Some(proxy)
}
}
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
pub fn open(&self,
url: DOMString,
@@ -314,7 +375,11 @@ impl WindowProxy {
},
"_parent" => {
// 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" => {
// Step 5
@@ -336,6 +401,10 @@ impl WindowProxy {
}
}
+ pub fn is_auxiliary(&self) -> bool {
+ self.opener.is_some()
+ }
+
pub fn discard_browsing_context(&self) {
self.discarded.set(true);
}
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 9e20a24e55b..8f4855c777b 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -157,6 +157,8 @@ struct InProgressLoad {
top_level_browsing_context_id: TopLevelBrowsingContextId,
/// The parent pipeline and frame type associated with this load, if any.
parent_info: Option<PipelineId>,
+ /// The opener, if this is an auxiliary.
+ opener: Option<BrowsingContextId>,
/// The current window size associated with this pipeline.
window_size: Option<WindowSizeData>,
/// Channel to the layout thread associated with this pipeline.
@@ -183,6 +185,7 @@ impl InProgressLoad {
browsing_context_id: BrowsingContextId,
top_level_browsing_context_id: TopLevelBrowsingContextId,
parent_info: Option<PipelineId>,
+ opener: Option<BrowsingContextId>,
layout_chan: Sender<message::Msg>,
window_size: Option<WindowSizeData>,
url: ServoUrl,
@@ -195,6 +198,7 @@ impl InProgressLoad {
browsing_context_id: browsing_context_id,
top_level_browsing_context_id: top_level_browsing_context_id,
parent_info: parent_info,
+ opener: opener,
layout_chan: layout_chan,
window_size: window_size,
activity: DocumentActivity::FullyActive,
@@ -569,6 +573,7 @@ impl ScriptThreadFactory for ScriptThread {
let browsing_context_id = state.browsing_context_id;
let top_level_browsing_context_id = state.top_level_browsing_context_id;
let parent_info = state.parent_info;
+ let opener = state.opener;
let mem_profiler_chan = state.mem_profiler_chan.clone();
let window_size = state.window_size;
let script_thread = ScriptThread::new(state,
@@ -583,7 +588,7 @@ impl ScriptThreadFactory for ScriptThread {
let origin = MutableOrigin::new(load_data.url.origin());
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);
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>> {
SCRIPT_THREAD_ROOT.with(|root| root.get().and_then(|script_thread| {
let script_thread = unsafe { &*script_thread };
@@ -1553,6 +1567,7 @@ impl ScriptThread {
new_pipeline_id,
browsing_context_id,
top_level_browsing_context_id,
+ opener,
load_data,
window_size,
pipeline_port,
@@ -1597,6 +1612,7 @@ impl ScriptThread {
browsing_context_id,
top_level_browsing_context_id,
parent_info,
+ opener,
layout_chan,
window_size,
load_data.url.clone(),
@@ -2025,6 +2041,16 @@ impl ScriptThread {
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
// script thread. If the browsing context already exists in the
// `window_proxies` map, we return it, otherwise we recursively
@@ -2034,7 +2060,8 @@ impl ScriptThread {
fn remote_window_proxy(&self,
global_to_clone: &GlobalScope,
top_level_browsing_context_id: TopLevelBrowsingContextId,
- pipeline_id: PipelineId)
+ pipeline_id: PipelineId,
+ opener: Option<BrowsingContextId>)
-> Option<DomRoot<WindowProxy>>
{
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));
}
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,
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));
Some(window_proxy)
}
@@ -2062,7 +2090,8 @@ impl ScriptThread {
window: &Window,
browsing_context_id: BrowsingContextId,
top_level_browsing_context_id: TopLevelBrowsingContextId,
- parent_info: Option<PipelineId>)
+ parent_info: Option<PipelineId>,
+ opener: Option<BrowsingContextId>)
-> DomRoot<WindowProxy>
{
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()) {
(_, Some(iframe)) => Some(window_from_node(&**iframe).window_proxy()),
(Some(parent_id), _) => self.remote_window_proxy(window.upcast(),
- top_level_browsing_context_id,
- parent_id),
+ top_level_browsing_context_id,
+ parent_id,
+ opener),
_ => None,
};
let window_proxy = WindowProxy::new(&window,
browsing_context_id,
top_level_browsing_context_id,
iframe.r().map(Castable::upcast),
- parent.r());
+ parent.r(),
+ opener);
self.window_proxies.borrow_mut().insert(browsing_context_id, Dom::from_ref(&*window_proxy));
window_proxy
}
@@ -2162,7 +2193,8 @@ impl ScriptThread {
let window_proxy = self.local_window_proxy(&window,
incomplete.browsing_context_id,
incomplete.top_level_browsing_context_id,
- incomplete.parent_info);
+ incomplete.parent_info,
+ incomplete.opener);
window.init_window_proxy(&window_proxy);
let last_modified = metadata.headers.as_ref().and_then(|headers| {
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 476f41ef0f1..be39ab71cb2 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -193,6 +193,8 @@ pub struct NewLayoutInfo {
pub browsing_context_id: BrowsingContextId,
/// Id of the top-level browsing context associated with this pipeline.
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.
pub load_data: LoadData,
/// Information about the initial window size.
@@ -521,6 +523,8 @@ pub struct InitialScriptState {
pub browsing_context_id: BrowsingContextId,
/// The ID of the top-level browsing context this script is part of.
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).
pub control_chan: IpcSender<ConstellationControlMsg>,
/// A port on which messages sent by the constellation to script can be received.
diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs
index 3668fd1e2fa..6dba5c00509 100644
--- a/components/script_traits/script_msg.rs
+++ b/components/script_traits/script_msg.rs
@@ -17,7 +17,8 @@ use embedder_traits::EmbedderMsg;
use euclid::{Size2D, TypedSize2D};
use gfx_traits::Epoch;
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::request::RequestInit;
use net_traits::storage_thread::StorageType;
@@ -105,6 +106,8 @@ pub enum ScriptMsg {
GetBrowsingContextId(PipelineId, IpcSender<Option<BrowsingContextId>>),
/// Get the parent info for a given pipeline.
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.
GetChildBrowsingContextId(BrowsingContextId, usize, IpcSender<Option<BrowsingContextId>>),
/// All pending loads are complete, and the `load` event for this pipeline
@@ -184,6 +187,7 @@ impl fmt::Debug for ScriptMsg {
GetClipboardContents(..) => "GetClipboardContents",
GetBrowsingContextId(..) => "GetBrowsingContextId",
GetParentInfo(..) => "GetParentInfo",
+ GetTopForBrowsingContext(..) => "GetParentBrowsingContext",
GetChildBrowsingContextId(..) => "GetChildBrowsingContextId",
LoadComplete => "LoadComplete",
LoadUrl(..) => "LoadUrl",
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index c5b3b544067..9887429ef07 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -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": [
[
{}
@@ -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.html",
@@ -587647,6 +587658,10 @@
"f82aa6f0abe0d16a8b132e531d165988af0af99f",
"testharness"
],
+ "html/browsers/windows/auxiliary-browsing-contexts/opener-setter.html": [
+ "85c52e0b42e19bdd78dda120320d66ddbb2103b4",
+ "testharness"
+ ],
"html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.js": [
"6d540ce97c94bff5845023098d0960d51dad62b4",
"testharness"
@@ -587675,6 +587690,10 @@
"6f43a5188c790577c4a1a03da270317eedba0fb0",
"support"
],
+ "html/browsers/windows/auxiliary-browsing-contexts/resources/opener-setter.html": [
+ "4112dae0cee66138a309b202a8d09d6b256c6d4d",
+ "support"
+ ],
"html/browsers/windows/browsing-context-names/choose-_blank-001.html": [
"a1416f2eb8437a8824a26a0e2e6aa6fdede37ffa",
"testharness"
diff --git a/tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/005.html.ini b/tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/005.html.ini
new file mode 100644
index 00000000000..20ee9003920
--- /dev/null
+++ b/tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/005.html.ini
@@ -0,0 +1,3 @@
+[005.html]
+ type: testharness
+ expected: ERROR
diff --git a/tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/007.html.ini b/tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/007.html.ini
index 04538ab47a0..aadbdc0beda 100644
--- a/tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/007.html.ini
+++ b/tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/007.html.ini
@@ -2,4 +2,3 @@
type: testharness
[Link with onclick javascript url and href navigation ]
expected: FAIL
-
diff --git a/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-closed.html.ini b/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-closed.html.ini
index d97cd045a92..9516c5bd53e 100644
--- a/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-closed.html.ini
+++ b/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-closed.html.ini
@@ -1,5 +1,5 @@
[opener-closed.html]
type: testharness
- expected: TIMEOUT
+ expected: CRASH
[An auxiliary browsing context should report `null` for `window.opener` when that browsing context is discarded]
- expected: TIMEOUT
+ expected: CRASH
diff --git a/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-multiple.html.ini b/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-multiple.html.ini
deleted file mode 100644
index 5f19cf016eb..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-multiple.html.ini
+++ /dev/null
@@ -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
diff --git a/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-noreferrer.html.ini b/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-noreferrer.html.ini
deleted file mode 100644
index dabad35e2ee..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-noreferrer.html.ini
+++ /dev/null
@@ -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
-
diff --git a/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.js.ini b/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.js.ini
deleted file mode 100644
index 9d293d228ba..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.window.js.ini
+++ /dev/null
@@ -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
-
diff --git a/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener.html.ini b/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener.html.ini
deleted file mode 100644
index 59a38204b5e..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/auxiliary-browsing-contexts/opener.html.ini
+++ /dev/null
@@ -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
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-001.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-001.html.ini
deleted file mode 100644
index de54ed6babc..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-001.html.ini
+++ /dev/null
@@ -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
-
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-002.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-002.html.ini
deleted file mode 100644
index da270341b6f..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-002.html.ini
+++ /dev/null
@@ -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
-
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-003.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-003.html.ini
deleted file mode 100644
index 34eeff13c09..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_blank-003.html.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[choose-_blank-003.html]
- type: testharness
- expected: TIMEOUT
- [Context created by link targeting "_blank" should retain opener reference]
- expected: TIMEOUT
-
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-001.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-001.html.ini
deleted file mode 100644
index 13139ca78c7..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-001.html.ini
+++ /dev/null
@@ -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
-
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-002.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-002.html.ini
deleted file mode 100644
index beaa956fd61..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-002.html.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[choose-_parent-002.html]
- type: testharness
- expected: ERROR
- [choosing _parent context: multiple nested contexts]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-003.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-003.html.ini
deleted file mode 100644
index a2bcdf6ed59..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-003.html.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[choose-_parent-003.html]
- type: testharness
- expected: ERROR
- [_parent should reuse window.parent context]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-004.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-004.html.ini
deleted file mode 100644
index 853b3be6979..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_parent-004.html.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[choose-_parent-004.html]
- type: testharness
- expected: TIMEOUT
- [choosing _parent context should be case-insensitive]
- expected: TIMEOUT
-
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_self-002.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_self-002.html.ini
deleted file mode 100644
index 8647f6bb351..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_self-002.html.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[choose-_self-002.html]
- type: testharness
- expected: TIMEOUT
- [choosing _self context should be case-insensitive]
- expected: TIMEOUT
-
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-001.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-001.html.ini
deleted file mode 100644
index 13bbd30d86b..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-001.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[choose-_top-001.html]
- type: testharness
- [Should choose current browsing context for "_top" if current is top]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-002.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-002.html.ini
deleted file mode 100644
index 464f944cdf3..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-002.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[choose-_top-002.html]
- type: testharness
- [Should choose top browsing context for "_top" if current is not top]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-003.html.ini b/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-003.html.ini
deleted file mode 100644
index ee59a5236c8..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/browsing-context-names/choose-_top-003.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[choose-_top-003.html]
- type: testharness
- [choosing _top context should be case-insensitive]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/browsers/windows/noreferrer-null-opener.html.ini b/tests/wpt/metadata/html/browsers/windows/noreferrer-null-opener.html.ini
deleted file mode 100644
index 5b7cd2d3c82..00000000000
--- a/tests/wpt/metadata/html/browsers/windows/noreferrer-null-opener.html.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[noreferrer-null-opener.html]
- type: testharness
- expected: TIMEOUT
- [rel=noreferrer nullifies window.opener]
- expected: TIMEOUT
-
diff --git a/tests/wpt/metadata/html/browsers/windows/targeting-cross-origin-nested-browsing-contexts.html.ini b/tests/wpt/metadata/html/browsers/windows/targeting-cross-origin-nested-browsing-contexts.html.ini
index 7e01a712d91..4ee3fbb8304 100644
--- a/tests/wpt/metadata/html/browsers/windows/targeting-cross-origin-nested-browsing-contexts.html.ini
+++ b/tests/wpt/metadata/html/browsers/windows/targeting-cross-origin-nested-browsing-contexts.html.ini
@@ -1,5 +1,4 @@
[targeting-cross-origin-nested-browsing-contexts.html]
type: testharness
- expected: TIMEOUT
[Targeting nested browsing contexts]
expected: FAIL
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.html b/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.html
new file mode 100644
index 00000000000..85c52e0b42e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/opener-setter.html
@@ -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>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/resources/opener-setter.html b/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/resources/opener-setter.html
new file mode 100644
index 00000000000..4112dae0cee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/resources/opener-setter.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>