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 
109             final MessageEvent event = new MessageEvent();
110             final URL currentURL = page.getUrl();
111             final String origin = currentURL.getProtocol() + "://" + currentURL.getHost() + ':' + currentURL.getPort();
112             event.initMessageEvent(Event.TYPE_MESSAGE, false, false, message, origin, "", w, transfer);
113             event.setParentScope(port_);
114             event.setPrototype(getPrototype(event.getClass()));
115 
116             final AbstractJavaScriptEngine<?> jsEngine = webWindow.getWebClient().getJavaScriptEngine();
117             final PostponedAction action = new PostponedAction(page, "MessagePort.postMessage") {
118                 @Override
119                 public void execute() {
120                     final HtmlUnitContextFactory cf = jsEngine.getContextFactory();
121                     cf.call(cx -> port_.dispatchEvent(event));
122                 }
123             };
124             jsEngine.addPostponedAction(action);
125         }
126     }
127 
128 }