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 * </p>
36 *
37 * @see <a href="https://developer.mozilla.org/en/WebSockets/WebSockets_reference/MessageEvent">
38 * Mozilla documentation</a>
39 * @author Ahmed Ashour
40 * @author Frank Danek
41 * @author Ronald Brill
42 */
43 @JsxClass
44 public class MessageEvent extends Event {
45
46 private Object data_;
47 private String origin_;
48 private String lastEventId_;
49 private Window source_;
50 private Object ports_;
51
52 /**
53 * Default constructor used to build the prototype.
54 */
55 public MessageEvent() {
56 super();
57 setType(TYPE_MESSAGE);
58 origin_ = "";
59 lastEventId_ = "";
60 data_ = JavaScriptEngine.UNDEFINED;
61 }
62
63 /**
64 * Constructs a Message Event with the provided data.
65 * @param data the data
66 */
67 public MessageEvent(final Object data) {
68 this();
69 data_ = data;
70 }
71
72 /**
73 * JavaScript constructor.
74 *
75 * @param type the event type
76 * @param details the event details (optional)
77 */
78 @Override
79 @JsxConstructor
80 public void jsConstructor(final String type, final ScriptableObject details) {
81 super.jsConstructor(type, details);
82
83 data_ = null;
84
85 String origin = "";
86 String lastEventId = "";
87 if (details != null && !JavaScriptEngine.isUndefined(details)) {
88 data_ = details.get("data");
89
90 final String detailOrigin = (String) details.get(HttpHeader.ORIGIN_LC);
91 if (detailOrigin != null) {
92 origin = detailOrigin;
93 }
94
95 final Object detailLastEventId = details.get("lastEventId");
96 if (detailLastEventId != null) {
97 lastEventId = JavaScriptEngine.toString(detailLastEventId);
98 }
99
100 source_ = null;
101 final Object detailSource = details.get("source");
102 if (detailSource instanceof Window window) {
103 source_ = window;
104 }
105 else if (detailSource instanceof WindowProxy proxy) {
106 source_ = proxy.getDelegee();
107 }
108 ports_ = details.get("ports");
109 }
110 origin_ = origin;
111 lastEventId_ = lastEventId;
112 }
113
114 /**
115 * Initializes an event object.
116 * @param type the event type
117 * @param canBubble can the event bubble
118 * @param cancelable can the event be canceled
119 * @param data the message
120 * @param origin the scheme, hostname and port of the document that caused the event
121 * @param lastEventId the identifier of the last event
122 * @param source the window object that contains the document that caused the event
123 * @param ports the message ports
124 */
125 @JsxFunction
126 public void initMessageEvent(
127 final String type,
128 final boolean canBubble,
129 final boolean cancelable,
130 final Object data,
131 final String origin,
132 final String lastEventId,
133 final Window source,
134 final Object ports) {
135 initEvent(type, canBubble, cancelable);
136 data_ = data;
137 origin_ = origin;
138 lastEventId_ = lastEventId;
139 source_ = source;
140
141 if (JavaScriptEngine.isUndefined(ports)
142 || ports instanceof NativeArray
143 || (ports instanceof Scriptable scriptable && ScriptableObject.hasProperty(scriptable, "length"))) {
144 ports_ = ports;
145 }
146 else {
147 throw JavaScriptEngine.typeError(
148 "Argument 8 of MessageEvent.initMessageEvent can't be converted to a sequence.");
149 }
150 }
151
152 /**
153 * Retrieves the data contained.
154 * @return the data contained
155 */
156 @JsxGetter
157 public Object getData() {
158 return data_;
159 }
160
161 /**
162 * Gets the URI of the document of origin.
163 * @return the origin
164 */
165 @JsxGetter
166 public String getOrigin() {
167 return origin_;
168 }
169
170 /**
171 * Sets the URI of the document of origin.
172 * @param origin the origin
173 */
174 public void setOrigin(final String origin) {
175 origin_ = origin;
176 }
177
178 /**
179 * Retrieves the identifier of the last event.
180 * @return the identified of the last event
181 */
182 @JsxGetter
183 public String getLastEventId() {
184 return lastEventId_;
185 }
186
187 /**
188 * Retrieves the data contained.
189 * @return the data contained
190 */
191 @JsxGetter
192 public Window getSource() {
193 return source_;
194 }
195
196 /**
197 * Returns the {@code ports} property.
198 * @return the {@code ports} property
199 */
200 @JsxGetter
201 public Object getPorts() {
202 return ports_;
203 }
204 }