1 /*
2 * Copyright (c) 2002-2026 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit.javascript.host.event;
16
17 import org.htmlunit.HttpHeader;
18 import org.htmlunit.corejs.javascript.NativeArray;
19 import org.htmlunit.corejs.javascript.Scriptable;
20 import org.htmlunit.corejs.javascript.ScriptableObject;
21 import org.htmlunit.javascript.JavaScriptEngine;
22 import org.htmlunit.javascript.configuration.JsxClass;
23 import org.htmlunit.javascript.configuration.JsxConstructor;
24 import org.htmlunit.javascript.configuration.JsxFunction;
25 import org.htmlunit.javascript.configuration.JsxGetter;
26 import org.htmlunit.javascript.host.Window;
27 import org.htmlunit.javascript.host.WindowProxy;
28
29 /**
30 * A JavaScript object for {@code MessageEvent}.
31 * <p>
32 * For general information on which properties and functions should be supported, see
33 * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#messageevent">
34 * Event definitions</a>.
35 *
36 * @see <a href="https://developer.mozilla.org/en/WebSockets/WebSockets_reference/MessageEvent">
37 * Mozilla documentation</a>
38 * @author Ahmed Ashour
39 * @author Frank Danek
40 * @author Ronald Brill
41 */
42 @JsxClass
43 public class MessageEvent extends Event {
44
45 private Object data_;
46 private String origin_;
47 private String lastEventId_;
48 private Window source_;
49 private Object ports_;
50
51 /**
52 * Default constructor used to build the prototype.
53 */
54 public MessageEvent() {
55 super();
56 setType(TYPE_MESSAGE);
57 origin_ = "";
58 lastEventId_ = "";
59 data_ = JavaScriptEngine.UNDEFINED;
60 }
61
62 /**
63 * Constructs a Message Event with the provided data.
64 * @param data the data
65 */
66 public MessageEvent(final Object data) {
67 this();
68 data_ = data;
69 }
70
71 /**
72 * JavaScript constructor.
73 *
74 * @param type the event type
75 * @param details the event details (optional)
76 */
77 @Override
78 @JsxConstructor
79 public void jsConstructor(final String type, final ScriptableObject details) {
80 super.jsConstructor(type, details);
81
82 data_ = null;
83
84 String origin = "";
85 String lastEventId = "";
86 if (details != null && !JavaScriptEngine.isUndefined(details)) {
87 data_ = details.get("data");
88
89 final String detailOrigin = (String) details.get(HttpHeader.ORIGIN_LC);
90 if (detailOrigin != null) {
91 origin = detailOrigin;
92 }
93
94 final Object detailLastEventId = details.get("lastEventId");
95 if (detailLastEventId != null) {
96 lastEventId = JavaScriptEngine.toString(detailLastEventId);
97 }
98
99 source_ = null;
100 final Object detailSource = details.get("source");
101 if (detailSource instanceof Window window) {
102 source_ = window;
103 }
104 else if (detailSource instanceof WindowProxy proxy) {
105 source_ = proxy.getDelegee();
106 }
107 ports_ = details.get("ports");
108 }
109 origin_ = origin;
110 lastEventId_ = lastEventId;
111 }
112
113 /**
114 * Initializes an event object.
115 * @param type the event type
116 * @param canBubble can the event bubble
117 * @param cancelable can the event be canceled
118 * @param data the message
119 * @param origin the scheme, hostname and port of the document that caused the event
120 * @param lastEventId the identifier of the last event
121 * @param source the window object that contains the document that caused the event
122 * @param ports the message ports
123 */
124 @JsxFunction
125 public void initMessageEvent(
126 final String type,
127 final boolean canBubble,
128 final boolean cancelable,
129 final Object data,
130 final String origin,
131 final String lastEventId,
132 final Window source,
133 final Object ports) {
134 initEvent(type, canBubble, cancelable);
135 data_ = data;
136 origin_ = origin;
137 lastEventId_ = lastEventId;
138 source_ = source;
139
140 if (JavaScriptEngine.isUndefined(ports)
141 || ports instanceof NativeArray
142 || (ports instanceof Scriptable scriptable && ScriptableObject.hasProperty(scriptable, "length"))) {
143 ports_ = ports;
144 }
145 else {
146 throw JavaScriptEngine.typeError(
147 "Argument 8 of MessageEvent.initMessageEvent can't be converted to a sequence.");
148 }
149 }
150
151 /**
152 * Retrieves the data contained.
153 * @return the data contained
154 */
155 @JsxGetter
156 public Object getData() {
157 return data_;
158 }
159
160 /**
161 * Gets the URI of the document of origin.
162 * @return the origin
163 */
164 @JsxGetter
165 public String getOrigin() {
166 return origin_;
167 }
168
169 /**
170 * Sets the URI of the document of origin.
171 * @param origin the origin
172 */
173 public void setOrigin(final String origin) {
174 origin_ = origin;
175 }
176
177 /**
178 * Retrieves the identifier of the last event.
179 * @return the identified of the last event
180 */
181 @JsxGetter
182 public String getLastEventId() {
183 return lastEventId_;
184 }
185
186 /**
187 * Retrieves the data contained.
188 * @return the data contained
189 */
190 @JsxGetter
191 public Window getSource() {
192 return source_;
193 }
194
195 /**
196 * Returns the {@code ports} property.
197 * @return the {@code ports} property
198 */
199 @JsxGetter
200 public Object getPorts() {
201 return ports_;
202 }
203 }