//
// UniWebView.cs
// Created by Wang Wei(@onevcat) on 2017-04-11.
//
// This file is a part of UniWebView Project (https://uniwebview.com)
// By purchasing the asset, you are allowed to use this code in as many as projects
// you want, only if you publish the final products under the name of the same account
// used for the purchase.
//
// This asset and all corresponding files (such as source code) are provided on an
// “as is” basis, without warranty of any kind, express of implied, including but not
// limited to the warranties of merchantability, fitness for a particular purpose, and
// noninfringement. In no event shall the authors or copyright holders be liable for any
// claim, damages or other liability, whether in action of contract, tort or otherwise,
// arising from, out of or in connection with the software or the use of other dealing in the software.
//
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
///
/// Main class of UniWebView. Any `GameObject` instance with this script represent a webview object in system.
/// Use this class to create, load, show and interact with a web view.
///
public class UniWebView: MonoBehaviour {
///
/// Delegate for page started event.
///
/// The web view component which raises this event.
/// The url which the web view begins to load.
public delegate void PageStartedDelegate(UniWebView webView, string url);
///
/// Raised when the web view starts loading a url.
///
/// This event will be invoked for both url loading with `Load` method or by a link navigating from page.
///
public event PageStartedDelegate OnPageStarted;
///
/// Delegate for page finished event.
///
/// The web view component which raises this event.
/// HTTP status code received from response.
/// The url which the web view loaded.
public delegate void PageFinishedDelegate(UniWebView webView, int statusCode, string url);
///
/// Raised when the web view finished to load a url successully.
///
/// This method will be invoked when a valid response received from the url, regardless the response status.
/// If a url loading fails before reaching to the server and getting a response, `OnPageErrorReceived` will be
/// raised instead.
///
public event PageFinishedDelegate OnPageFinished;
///
/// Delegate for page error received event.
///
/// The web view component which raises this event.
///
/// The error code which indicates the error type.
/// It is different from systems and platforms.
///
/// The error message which indicates the error.
public delegate void PageErrorReceivedDelegate(UniWebView webView, int errorCode, string errorMessage);
///
/// Raised when an error encountered during the loading process.
/// Such as host not found or no Internet connection will raise this event.
///
public event PageErrorReceivedDelegate OnPageErrorReceived;
///
/// Delegate for message received event.
///
/// The web view component which raises this event.
/// Message received from web view.
public delegate void MessageReceivedDelegate(UniWebView webView, UniWebViewMessage message);
///
/// Raised when a message from web view is received.
///
/// Generally, the message comes from a navigation to
/// a scheme which is observed by current web view. You could use `AddUrlScheme` and
/// `RemoveUrlScheme` to manipulate the scheme list.
///
/// "uniwebview://" scheme is default in the list, so a clicking on link starts with "uniwebview://"
/// will raise this event, if it is not removed.
///
public event MessageReceivedDelegate OnMessageReceived;
///
/// Delegate for should close event.
///
/// The web view component which raises this event.
/// Whether the web view should be closed and destroyed.
public delegate bool ShouldCloseDelegate(UniWebView webView);
///
/// Raised when the web view is about to close itself.
///
/// This event is raised when the users close the web view by Back button on Android, Done button on iOS,
/// or Close button on Unity Editor. It gives a chance to make final decision whether the web view should
/// be closed and destroyed. You should also clean all related resources you created (such as a reference to
/// the web view.)
///
public event ShouldCloseDelegate OnShouldClose;
///
/// Delegate for code keycode received event.
///
/// The web view component which raises this event.
/// The key code of pressed key. See [Android API for keycode](https://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_0) to know the possible values.
public delegate void KeyCodeReceivedDelegate(UniWebView webView, int keyCode);
///
/// Raised when a key (like back button or volume up) on the device is pressed.
///
/// This event only raised on Android. It is useful when you disabled the back button but still need to
/// get the back button event. On iOS, user's key action is not avaliable and this event will never be
/// raised.
///
public event KeyCodeReceivedDelegate OnKeyCodeReceived;
///
/// Delegate for orientation changed event.
///
/// The web view component which raises this event.
/// The screen orientation for current state.
public delegate void OrientationChangedDelegate(UniWebView webView, ScreenOrientation orientation);
///
/// Raised when the screen orientation is changed. It is a good time to set the web view frame if you
/// need to support multiple orientations in your game.
///
public event OrientationChangedDelegate OnOrientationChanged;
///
/// Delegate for content loading terminated event.
///
/// The web view component which raises this event.
public delegate void OnWebContentProcessTerminatedDelegate(UniWebView webView);
///
/// Raised when on iOS, when system calls `webViewWebContentProcessDidTerminate` method.
/// It is usually due to a low memory when loading the web content and leave you a blank white screen.
/// You need to free as much as memory you could and then do a page reload.
///
public event OnWebContentProcessTerminatedDelegate OnWebContentProcessTerminated;
private string id = Guid.NewGuid().ToString();
private UniWebViewNativeListener listener;
private bool isPortrait;
[SerializeField]
#pragma warning disable 0649
private string urlOnStart;
[SerializeField]
private bool showOnStart = false;
[SerializeField]
private bool fullScreen;
[SerializeField]
private bool useToolbar;
[SerializeField]
private UniWebViewToolbarPosition toolbarPosition;
#pragma warning restore 0649
// Action callback holders
private Dictionary actions = new Dictionary();
private Dictionary> payloadActions = new Dictionary>();
[SerializeField]
private Rect frame;
///
/// Get or Set the frame of current web view. The value is based on current `Screen.width` and `Screen.height`.
/// The first two values of `Rect` is `x` and `y` position and the followed two `width` and `height`.
///
public Rect Frame {
get { return frame; }
set {
frame = value;
UpdateFrame();
}
}
[SerializeField]
private RectTransform referenceRectTransform;
///
/// A reference rect transform which the web view should change its position and size to.
/// Set it to a Unity UI element (which contains a `RectTransform`) under a canvas to determine
/// the web view frame by a certain UI element.
///
/// By using this, you could get benefit from [Multiple Resolutions UI](https://docs.unity3d.com/Manual/HOWTO-UIMultiResolution.html).
///
///
public RectTransform ReferenceRectTransform {
get {
return referenceRectTransform;
}
set {
referenceRectTransform = value;
UpdateFrame();
}
}
private bool started;
///
/// The url of current loaded web page.
///
public string Url {
get { return UniWebViewInterface.GetUrl(listener.Name); }
}
///
/// Update and set current frame of web view to match the setting.
///
/// This is useful if the `referenceRectTransform` is changed and you need to sync the frame change
/// to the web view. This method follows the frame determining rules.
///
public void UpdateFrame() {
Rect rect = NextFrameRect();
UniWebViewInterface.SetFrame(listener.Name, (int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
}
Rect NextFrameRect() {
if (referenceRectTransform == null) {
UniWebViewLogger.Instance.Info("Using Frame setting to determine web view frame.");
return frame;
} else {
UniWebViewLogger.Instance.Info("Using reference RectTransform to determine web view frame.");
var worldCorners = new Vector3[4];
referenceRectTransform.GetWorldCorners(worldCorners);
var bottomLeft = worldCorners[0];
var topLeft = worldCorners[1];
var topRight = worldCorners[2];
var bottomRight = worldCorners[3];
var canvas = referenceRectTransform.GetComponentInParent