View Javadoc
1   /*
2    * Copyright (c) 2002-2025 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   * A JavaScript object for {@code MessagePort}.
36   *
37   * @author Ahmed Ashour
38   * @author Ronald Brill
39   */
40  @JsxClass
41  public class MessagePort extends EventTarget {
42  
43      private MessagePort port_;
44  
45      /**
46       * Default constructor.
47       */
48      public MessagePort() {
49          super();
50      }
51  
52      /**
53       * JavaScript constructor.
54       */
55      @Override
56      @JsxConstructor
57      public void jsConstructor() {
58          super.jsConstructor();
59      }
60  
61      /**
62       * Ctor with the specified {@code port}.
63       * @param port the port
64       */
65      public MessagePort(final MessagePort port) {
66          super();
67          port_ = port;
68      }
69  
70      /**
71       * Returns the value of the window's {@code onmessage} property.
72       * @return the value of the window's {@code onmessage} property
73       */
74      @JsxGetter
75      public Function getOnmessage() {
76          return getHandlerForJavaScript(Event.TYPE_MESSAGE);
77      }
78  
79      /**
80       * Sets the value of the window's {@code onmessage} property.
81       * @param onmessage the value of the window's {@code onmessage} property
82       */
83      @JsxSetter
84      public void setOnmessage(final Object onmessage) {
85          setHandlerForJavaScript(Event.TYPE_MESSAGE, onmessage);
86      }
87  
88      private Function getHandlerForJavaScript(final String eventName) {
89          return getEventListenersContainer().getEventHandler(eventName);
90      }
91  
92      private void setHandlerForJavaScript(final String eventName, final Object handler) {
93          getEventListenersContainer().setEventHandler(eventName, handler);
94      }
95  
96      /**
97       * Posts a message.
98       * @param message the object passed to the window
99       * @param transfer an optional sequence of Transferable objects
100      * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage">MDN documentation</a>
101      */
102     @JsxFunction
103     public void postMessage(final String message, final Object transfer) {
104         if (port_ != null) {
105             final Window w = getWindow();
106             final WebWindow webWindow = w.getWebWindow();
107             final Page page = webWindow.getEnclosedPage();
108             final URL currentURL = page.getUrl();
109             final MessageEvent event = new MessageEvent();
110             final String origin = currentURL.getProtocol() + "://" + currentURL.getHost() + ':' + currentURL.getPort();
111             event.initMessageEvent(Event.TYPE_MESSAGE, false, false, message, origin, "", w, transfer);
112             event.setParentScope(port_);
113             event.setPrototype(getPrototype(event.getClass()));
114 
115             final AbstractJavaScriptEngine<?> jsEngine = webWindow.getWebClient().getJavaScriptEngine();
116             final PostponedAction action = new PostponedAction(page, "MessagePort.postMessage") {
117                 @Override
118                 public void execute() {
119                     final HtmlUnitContextFactory cf = jsEngine.getContextFactory();
120                     cf.call(cx -> port_.dispatchEvent(event));
121                 }
122             };
123             jsEngine.addPostponedAction(action);
124         }
125     }
126 
127 }