Limitations of 2D WebView for WebGL

2D WebView for WebGL brings the 2D functionality of 3D WebView to Unity's HTML5 WebGL player. It functions by loading web content into an <iframe> element, which works well for many 2D scenarios, but due to browser limitations, it has significant limitations compared to the other 3D WebView packages:

Other limitations:

2D only limitation

3D WebView normally works by rendering web content to a texture that is shown in Unity. Unfortunately, WebGL doesn't provide a suitable way to render an iframe to a texture, so 2D WebView for WebGL only supports Native 2D Mode. This means that it only supports 2D screen space (it doesn't support 3D world space), and it's not possible to render web content to a texture, render other Unity objects or UI elements in front of a webview, or rotate a webview. In the future, I may develop a separate cloud-based version of 3D WebView that will support 3D in WebGL. If you want me to add you to the waitlist for it, please contact me.

X-Frame-Options limitation

2D WebView for WebGL is unable to load websites that block iframes by sending an X-Frame-Options header. For example, many popular sites like Google and Facebook block iframes using X-Frame-Options. You can determine whether 2D WebView for WebGL can load a given URL by using this URL tester:

Cross-origin domain limitation

For security purposes, browsers prevent a webpage from accessing the content of an iframe if the webpage's URL and the iframe's URL have different domains. For 2D WebView, this means that its IWebView APIs work when the webview's URL matches the domain of the Unity app (for example, when the application loads an HTML file from StreamingAssets or loads a different webpage hosted on your own domain), but most IWebView APIs do not work if the webview's URL is from a different domain (for example, bing.com or any other 3rd party site). When the IWebView APIs are disabled, the user can still click, scroll, and type into the webview directly, but the application cannot interact with the affected IWebView APIs programmatically.

The following IWebView APIs only work when the webview's URL matches the domain of the Unity app:

Other notes about this limitation:

"Minimal" WebGL template not supported / container element required

2D WebView for WebGL supports Unity's "Default" and "PWA" WebGL templates, but doesn't support the "Minimal" template. In Unity's "Default" and "PWA" templates, the <canvas> element is nested inside of a parent container element like this:

<div id="unity-container">
  <canvas id="unity-canvas"></canvas>
</div>

The elements' styles are set such that the container and canvas have the same position and dimensions (i.e. they have the same rect because the canvas occupies the entirety of the container). 2D WebView for WebGL works by adding <iframe> elements inside the container element so that the iframes are rendered in front of the canvas. Unity's "Minimal" template doesn't include a container element, so 2D WebView for WebGL is unable to support it.

2D WebView can also work with a custom WebGL template as long as the template includes a parent container element with the same dimensions as the <canvas> element, like Unity's "Default" template. 2D WebView automatically detects the container element if its id is set to "unity-container". If the container element's id is set to a different value, then the application must call WebGLWebView.SetUnityContainerElementID() to pass the id value to 2D WebView.

How to use the window.vuplex JavaScript API when the page is from a different domain

Due to the cross-origin domain limitation, 2D WebView for WebGL is unable to automatically inject the window.vuplex JavaScript API for message passing into a web page if the page's URL is from a different domain than the Unity WebGL app. However, you can add the window.vuplex JavaScript API to a web page by manually adding the following JavaScript to the page (i.e. via a <script> tag):

class VuplexPolyfill {
  constructor() {
    this._listeners = {};
    window.addEventListener('message', this._handleWindowMessage.bind(this));
  }

  addEventListener(eventName, listener) {
    if (!this._listeners[eventName]) {
      this._listeners[eventName] = [];
    }
    if (this._listeners[eventName].indexOf(listener) === -1) {
      this._listeners[eventName].push(listener);
    }
  }

  removeEventListener(eventName, listener) {
    if (!this._listeners[eventName]) {
      return;
    }
    const index = this._listeners[eventName].indexOf(listener);
    if (index !== -1) {
      this._listeners[eventName].splice(index, 1);
    }
  }

  postMessage(message) {
    // Don't pass a string to JSON.stringify() because it adds extra quotes.
    const messageString = typeof message === 'string' ? message : JSON.stringify(message);
    parent.postMessage({
      type: 'vuplex.postMessage',
      message: messageString
    }, '*')
  }

  _emit(eventName, ...args) {
    if (!this._listeners[eventName]) {
      return;
    }
    for (const listener of this._listeners[eventName]) {
      try {
        listener(...args);
      } catch (error) {
        console.error(`An error occurred while invoking the '${eventName}' event handler.`, error);
      }
    }
  }

  _handleWindowMessage(event) {
    if (event.data && event.data.type === 'vuplex.postMessage') {
      // Dispatch the new window vuplexmessage event added in v4.11.
      const value = event.data.message;
      const vuplexMessageEvent = new Event('vuplexmessage');
      vuplexMessageEvent.value = value;
      vuplexMessageEvent.data = value;
      window.dispatchEvent(vuplexMessageEvent);
      // Dispatch the older window.vuplex message event.
      this._emit('message', { value, data: value });
    }
  };
}

if (!window.vuplex) {
  window.vuplex = new VuplexPolyfill();
}

Unity keyboard detection APIs don't work when a webview is focused

When the user clicks on a webview, their web browser shifts input focus from the Unity game view to the webview's <iframe> element. While the iframe is focused, the Unity application is unable to detect keyboard input (i.e. keyboard APIs like Input.GetKeyDown() don't work). By default, the Unity game view isn't refocused until the user clicks on it, at which point the Unity application is once again able to detect keyboard input. However, the application can optionally use WebGLWebView.SetFocusUnityOnHover() and FocusUnity() to automatically refocus the Unity game view without requiring the user to actually click on it. Please note that these APIs were added in 3D WebView v4.10 and v4.8, respectively.