瀏覽代碼

LibWeb: Implement the `window.opener` attribute

This returns a reference to the window that opened the current window.
Tim Ledbetter 1 年之前
父節點
當前提交
fc1f037cd1

+ 5 - 0
Tests/LibWeb/Text/expected/HTML/Window-opener.txt

@@ -0,0 +1,5 @@
+  window.opener initial value: null
+window.opener after setting to "test": test
+iframe contentWindow.opener initial value is the current window object: true
+iframe contentWindow.opener after setting to null: null
+iframe contentWindow.opener after setting to "test": test

+ 20 - 0
Tests/LibWeb/Text/input/HTML/Window-opener.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<script src="../include.js"></script>
+<iframe name="testFrame"></iframe>
+<script>    
+    asyncTest(done => {
+        println(`window.opener initial value: ${window.opener}`);
+        window.opener = "test";
+        println(`window.opener after setting to "test": ${window.opener}`);
+        const frame = document.querySelector("iframe");
+        frame.onload = () => {
+            println(`iframe contentWindow.opener initial value is the current window object: ${frame.contentWindow.opener === window}`);
+            frame.contentWindow.opener = null;
+            println(`iframe contentWindow.opener after setting to null: ${frame.contentWindow.opener}`);
+            frame.contentWindow.opener = "test";
+            println(`iframe contentWindow.opener after setting to "test": ${frame.contentWindow.opener}`);
+            done();
+        }
+        window.open("about:srcdoc", "testFrame");
+    });
+</script>

+ 35 - 0
Userland/Libraries/LibWeb/HTML/Window.cpp

@@ -946,6 +946,41 @@ JS::GCPtr<WindowProxy const> Window::top() const
     return navigable->top_level_traversable()->active_window_proxy();
     return navigable->top_level_traversable()->active_window_proxy();
 }
 }
 
 
+// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-opener
+JS::GCPtr<WindowProxy const> Window::opener() const
+{
+    // 1. Let current be this's browsing context.
+    auto const* current = browsing_context();
+
+    // 2. If current is null, then return null.
+    if (!current)
+        return {};
+
+    // 3. If current's opener browsing context is null, then return null.
+    auto opener_browsing_context = current->opener_browsing_context();
+    if (!opener_browsing_context)
+        return {};
+
+    // 4. Return current's opener browsing context's WindowProxy object.
+    return opener_browsing_context->window_proxy();
+}
+
+WebIDL::ExceptionOr<void> Window::set_opener(JS::Value value)
+{
+    // 1. If the given value is null and this's browsing context is non-null, then set this's browsing context's opener browsing context to null.
+    auto* browsing_context = this->browsing_context();
+    if (value.is_null() && browsing_context)
+        browsing_context->set_opener_browsing_context(nullptr);
+
+    // 2. If the given value is non-null, then perform ? DefinePropertyOrThrow(this, "opener", { [[Value]]: the given value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }).
+    if (!value.is_null()) {
+        static JS::PropertyKey opener_property_key { "opener", JS::PropertyKey::StringMayBeNumber::No };
+        TRY(define_property_or_throw(opener_property_key, { .value = value, .writable = true, .enumerable = true, .configurable = true }));
+    }
+
+    return {};
+}
+
 // https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-parent
 // https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-parent
 JS::GCPtr<WindowProxy const> Window::parent() const
 JS::GCPtr<WindowProxy const> Window::parent() const
 {
 {

+ 2 - 0
Userland/Libraries/LibWeb/HTML/Window.h

@@ -144,6 +144,8 @@ public:
     JS::NonnullGCPtr<WindowProxy> frames() const;
     JS::NonnullGCPtr<WindowProxy> frames() const;
     u32 length();
     u32 length();
     JS::GCPtr<WindowProxy const> top() const;
     JS::GCPtr<WindowProxy const> top() const;
+    JS::GCPtr<WindowProxy const> opener() const;
+    WebIDL::ExceptionOr<void> set_opener(JS::Value);
     JS::GCPtr<WindowProxy const> parent() const;
     JS::GCPtr<WindowProxy const> parent() const;
     JS::GCPtr<DOM::Element const> frame_element() const;
     JS::GCPtr<DOM::Element const> frame_element() const;
     WebIDL::ExceptionOr<JS::GCPtr<WindowProxy>> open(Optional<String> const& url, Optional<String> const& target, Optional<String> const& features);
     WebIDL::ExceptionOr<JS::GCPtr<WindowProxy>> open(Optional<String> const& url, Optional<String> const& target, Optional<String> const& features);

+ 1 - 0
Userland/Libraries/LibWeb/HTML/Window.idl

@@ -35,6 +35,7 @@ interface Window : EventTarget {
     [Replaceable] readonly attribute WindowProxy frames;
     [Replaceable] readonly attribute WindowProxy frames;
     [Replaceable] readonly attribute unsigned long length;
     [Replaceable] readonly attribute unsigned long length;
     [LegacyUnforgeable] readonly attribute WindowProxy? top;
     [LegacyUnforgeable] readonly attribute WindowProxy? top;
+    attribute any opener;
     [Replaceable] readonly attribute WindowProxy? parent;
     [Replaceable] readonly attribute WindowProxy? parent;
     readonly attribute Element? frameElement;
     readonly attribute Element? frameElement;
     WindowProxy? open(optional USVString url = "", optional DOMString target = "_blank", optional [LegacyNullToEmptyString] DOMString features = "");
     WindowProxy? open(optional USVString url = "", optional DOMString target = "_blank", optional [LegacyNullToEmptyString] DOMString features = "");