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:
- It only supports Native 2D Mode, so the 2D CanvasWebViewPrefab works, but the 3D WebViewPrefab does not. Also, it's not possible to place other Unity objects or UI elements in front of a webview. You can read more about this limitation here.
- It's 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 read more about this limitation and test if a URL is compatible here.
- When the webview's URL has a different domain than the Unity app, most of the IWebView methods become disabled. You can read more about this limitation here. HTML loaded with LoadHtml() also faces this limitation, but an alternative that supports the IWebView methods is to load the HTML from StreamingAssets instead.
- When the Unity app is served over HTTPS (i.e. its URL starts with https://), webviews cannot load insecure HTTP URLs (i.e. https:// must be used instead of http://).
- The following IWebView methods are not supported and are ignored at runtime:
- The following IWebView methods have limitations:
- LoadUrl(url, additionalHeaders) is unable to send additional headers due to browser limitations, so it loads the URL without additional headers.
- CanGoBack() and CanGoForward() both return whether the webview can either go back or forward. In other words, both methods return true if the webview can go either back or foward, and both return false if the webview can't go back or forward.
- LoadProgressChanged only indicates the ProgressChangeType.Started and Finished events, and it is unable to indicate the Failed or Updated events.
Other limitations:
- How to use the window.vuplex JavaScript API when the page is from a different domain
- Unity Input class methods don't work when a webview is focused
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), it's not possible to render web content to a texture, and it's not possible to render other Unity objects or UI elements in front of a webview. However, I'm currently developing 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:
- CanGoBack()
- CanGoForward()
- CloseRequested
- Click()
- ConsoleMessageLogged
- ExecuteJavaScript()
- FocusedInputFieldChanged
- GoBack()
- GoForward()
- PageLoadScripts
- Scroll()
- SelectAll()
- SendKey()
- SetFocused()
- Title
- TitleChanged
- Url
- UrlChanged
Other notes about this limitation:
LoadHtml() works by loading content as a data URL, which browsers also consider as a different domain. So, HTML loaded with LoadHtml() also faces this limitation, but an alternative that supports the IWebView methods is to load the HTML from StreamingAssets instead.
An application can check check whether the IWebView APIs listed above are enabled at any time by calling WebGLWebView.CanAccessIFrameContent().
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') {
this._emit('message', { data: event.data.message });
}
};
}
if (!window.vuplex) {
window.vuplex = new VuplexPolyfill();
}Unity Input class methods don't work when a webview is focused
When the application creates a webview, the webview's <iframe> element takes focus on the web page. While the iframe is focused, Unity's Input class methods like Input.GetKey() and GetMouseButton() don't work. So, in order to use those Input methods, it's necessary to first unfocus the webview like this:
if (canvasWebViewPrefab.WebView != null) {
canvasWebViewPrefab.WebView.SetFocused(false);
}
var mouseDown = Input.GetMouseButtonDown(0);Please note that this approach of unfocusing the webview requires 3D WebView v4.2 or newer.
