View Javadoc
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;
16  
17  import java.net.URL;
18  
19  import org.htmlunit.Page;
20  import org.htmlunit.WebWindow;
21  import org.htmlunit.corejs.javascript.Function;
22  import org.htmlunit.javascript.AbstractJavaScriptEngine;
23  import org.htmlunit.javascript.HtmlUnitContextFactory;
24  import org.htmlunit.javascript.PostponedAction;
25  import org.htmlunit.javascript.configuration.JsxClass;
26  import org.htmlunit.javascript.configuration.JsxConstructor;
27  import org.htmlunit.javascript.configuration.JsxFunction;
28  import org.htmlunit.javascript.configuration.JsxGetter;
29  import org.htmlunit.javascript.configuration.JsxSetter;
30  import org.htmlunit.javascript.host.event.Event;
31  import org.htmlunit.javascript.host.event.EventTarget;
32  import org.htmlunit.javascript.host.event.MessageEvent;
33  
34  /**
35   * JavaScript host object for {@code MessagePort}.
36   *
37   * @author Ahmed Ashour
38   * @author Ronald Brill
39   *
40   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/MessagePort">MDN Documentation</a>
41   */
42  @JsxClass
43  public class MessagePort extends EventTarget {
44  
45      private MessagePort port_;
46  
47      /**
48       * Default constructor.
49       */
50      public MessagePort() {
51          super();
52      }
53  
54      /**
55       * Creates an instance of this object.
56       */
57      @Override
58      @JsxConstructor
59      public void jsConstructor() {
60          super.jsConstructor();
61      }
62  
63      /**
64       * Creates an instance connected to the specified port.
65       *
66       * @param port the port to connect to
67       */
68      public MessagePort(final MessagePort port) {
69          super();
70          port_ = port;
71      }
72  
73      /**
74       * Returns the {@code onmessage} event handler.
75       *
76       * @return the {@code onmessage} event handler
77       */
78      @JsxGetter
79      public Function getOnmessage() {
80          return getHandlerForJavaScript(Event.TYPE_MESSAGE);
81      }
82  
83      /**
84       * Sets the {@code onmessage} event handler.
85       *
86       * @param onmessage the {@code onmessage} event handler
87       */
88      @JsxSetter
89      public void setOnmessage(final Object onmessage) {
90          setHandlerForJavaScript(Event.TYPE_MESSAGE, onmessage);
91      }
92  
93      private Function getHandlerForJavaScript(final String eventName) {
94          return getEventListenersContainer().getEventHandler(eventName);
95      }
96  
97      private void setHandlerForJavaScript(final String eventName, final Object handler) {
98          getEventListenersContainer().setEventHandler(eventName, handler);
99      }
100 
101     /**
102      * Posts a message to the connected port.
103      *
104      * @param message the object to post
105      * @param transfer an optional sequence of transferable objects
106      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage">MDN Documentation</a>
107      */
108     @JsxFunction
109     public void postMessage(final String message, final Object transfer) {
110         if (port_ != null) {
111             final Window w = getWindow();
112             final WebWindow webWindow = w.getWebWindow();
113             final Page page = webWindow.getEnclosedPage();
114 
115             final MessageEvent event = new MessageEvent();
116             final URL currentURL = page.getUrl();
117             final String origin = currentURL.getProtocol() + "://" + currentURL.getHost() + ':' + currentURL.getPort();
118             event.initMessageEvent(Event.TYPE_MESSAGE, false, false, message, origin, "", w, transfer);
119             event.setParentScope(getParentScope());
120             event.setPrototype(getPrototype(event.getClass()));
121 
122             final AbstractJavaScriptEngine<?> jsEngine = webWindow.getWebClient().getJavaScriptEngine();
123             final PostponedAction action = new PostponedAction(page, "MessagePort.postMessage") {
124                 @Override
125                 public void execute() {
126                     final HtmlUnitContextFactory cf = jsEngine.getContextFactory();
127                     cf.call(cx -> port_.dispatchEvent(event));
128                 }
129             };
130             jsEngine.addPostponedAction(action);
131         }
132     }
133 
134     /**
135      * Starts the sending of messages queued on the port.
136      * Only needed when using {@code EventTarget.addEventListener}; it is implied when using {@code onmessage}.
137      *
138      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/start">MDN Documentation</a>
139      */
140     @JsxFunction
141     public void start() {
142         // dummy for the moment
143     }
144 
145     /**
146      * Disconnects the port so it is no longer active.
147      *
148      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/close">MDN Documentation</a>
149      */
150     @JsxFunction
151     public void close() {
152         // dummy for the moment
153     }
154 }