/* * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using ElmSharp; using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace Tizen.WebView { /// /// A view used to render the web contents. /// /// 4 public class WebView: EvasObject { private static IDictionary _javaScriptMessageHandlerMap = new Dictionary(); private IntPtr _handle; private IntPtr _realHandle; private Context _context; private Settings _settings; // focus dummy private SmartEvent _focusIn; private SmartEvent _focusOut; // Smart events private SmartEvent _loadStarted; private SmartEvent _loadFinished; private SmartEvent _loadError; private SmartEvent _titleChanged; private SmartEvent _urlChanged; /// /// Event that occurs when the load is started. /// /// 4 public event EventHandler LoadStarted; /// /// Event that occurs when the load is finished. /// /// 4 public event EventHandler LoadFinished; /// /// Event that occurs when the load throws an error. /// /// 4 public event EventHandler LoadError; /// /// Event that occurs when the title of the main frame is changed. /// /// 4 public event EventHandler TitleChanged; /// /// Event that occurs when the URL of the main frame is changed. /// /// 4 public event EventHandler UrlChanged; /// /// Current URL of the main frame. /// /// 4 public string Url { get { return Interop.ChromiumEwk.ewk_view_url_get(_realHandle); } } /// /// Current title of the main frame. /// /// 4 public string Title { get { return Interop.ChromiumEwk.ewk_view_title_get(_realHandle); } } /// /// Current user agent string of this view. /// /// 4 public string UserAgent { get { return Interop.ChromiumEwk.ewk_view_user_agent_get(_realHandle); } set { Interop.ChromiumEwk.ewk_view_user_agent_set(_realHandle, value); } } /// /// Whether a view has the focus. /// /// 4 public bool HasFocus { get { return Interop.ChromiumEwk.ewk_view_focus_get(_realHandle); } } /// /// Creates a WebView object. /// /// Parent object of the WebView. /// 4 public WebView(EvasObject parent) : base(parent) { InitializeSmartEvent(); } /// /// Gets the context object of this view. /// /// The context object of this view. /// 4 public Context GetContext() { if (_context == null) { IntPtr contextHandle = Interop.ChromiumEwk.ewk_view_context_get(_realHandle); if (contextHandle == IntPtr.Zero) { return null; } _context = new Context(contextHandle); } return _context; } /// /// Gets the settings object of this view. /// /// The settings object of this view. /// 4 public Settings GetSettings() { if (_settings == null) { IntPtr settingsHandle = Interop.ChromiumEwk.ewk_view_settings_get(_realHandle); if (settingsHandle == IntPtr.Zero) { return null; } _settings = new Settings(settingsHandle); } return _settings; } /// /// Gets the back/forward list object of this view. /// /// The BackForward List object of this view. /// 6 public BackForwardList GetBackForwardList() { IntPtr backforwardlistHandle = Interop.ChromiumEwk.ewk_view_back_forward_list_get(_realHandle); if (backforwardlistHandle == IntPtr.Zero) { return null; } return new BackForwardList(backforwardlistHandle); } /// /// Clear the back/forward list object of this view. /// /// 6 public void ClearBackForwardList() { Interop.ChromiumEwk.ewk_view_back_forward_list_clear(_realHandle); } /// /// Asks the object to load the given URL. /// /// /// You can only be sure that the URL changes after UrlChanged event. /// /// The uniform resource identifier to load. /// 4 public void LoadUrl(string url) { Interop.ChromiumEwk.ewk_view_url_set(_realHandle, url); } /// /// Loads the specified HTML string as the content of the view. /// /// HTML data to load. /// Base URL used for relative paths to external objects. /// 4 public void LoadHtml(string html, string baseUrl) { Interop.ChromiumEwk.ewk_view_html_string_load(_realHandle, html, baseUrl, null); } /// /// Asks the main frame to stop loading. /// /// 4 public void StopLoading() { Interop.ChromiumEwk.ewk_view_stop(_realHandle); } /// /// Asks the main frame to reload the current document. /// /// 4 public void Reload() { Interop.ChromiumEwk.ewk_view_reload(_realHandle); } /// /// Asks the main frame to navigate back in history. /// /// 4 public void GoBack() { Interop.ChromiumEwk.ewk_view_back(_realHandle); } /// /// Asks the main frame to navigate forward in history. /// /// 4 public void GoForward() { Interop.ChromiumEwk.ewk_view_forward(_realHandle); } /// /// Checks whether it is possible to navigate backward one item in history. /// /// Whether it is possible to navigate backward one item in history. /// 4 public bool CanGoBack() { return Interop.ChromiumEwk.ewk_view_back_possible(_realHandle); } /// /// Checks whether it is possible to navigate forward one item in history. /// /// Whether it is possible to navigate forward one item in history. /// 4 public bool CanGoForward() { return Interop.ChromiumEwk.ewk_view_forward_possible(_realHandle); } /// /// Injects the supplied javascript message handler into the view. /// /// The message callback. /// The name used to expose the object in JavaScript. /// 'true' on success, otherwise 'false'. /// 4 public bool AddJavaScriptMessageHandler(string name, JavaScriptMessageHandler handler) { lock (_javaScriptMessageHandlerMap) { if (_javaScriptMessageHandlerMap.ContainsKey(name)) { return false; } _javaScriptMessageHandlerMap[name] = handler; } Interop.ChromiumEwk.ScriptMessageCallback callback = (handle, message) => { JavaScriptMessage convertedMessage = new JavaScriptMessage(message); lock (_javaScriptMessageHandlerMap) { if (_javaScriptMessageHandlerMap.ContainsKey(convertedMessage.Name)) { _javaScriptMessageHandlerMap[convertedMessage.Name](convertedMessage); } } }; if (!Interop.ChromiumEwk.ewk_view_javascript_message_handler_add(_realHandle, callback, name)) { lock (_javaScriptMessageHandlerMap) { _javaScriptMessageHandlerMap.Remove(name); return false; } } return true; } /// /// Requests the execution of a given name and the result to the JavaScript runtime. /// /// The name used to expose the object in JavaScript. /// The result to the JavaScript runtime. /// 4 public void EvalWithResult(string name, string result) { Interop.ChromiumEwk.ewk_view_evaluate_javascript(_realHandle, name, result); } /// /// Requests the execution of the given script. /// /// The JavaScript code string to execute. /// 4 public void Eval(string script) { Interop.ChromiumEwk.ewk_view_script_execute(_realHandle, script, null, IntPtr.Zero); } /// /// Requests to set or unset a view as the currently focused one. /// /// 'true' to set the focus on the view, 'false' to remove the focus from the view. /// 4 public void SetFocus(bool focused) { Interop.ChromiumEwk.ewk_view_focus_set(_realHandle, focused); } /// /// Creates a widget handle. /// /// Parent EvasObject. /// IntPtr of the widget handle. /// 4 protected override IntPtr CreateHandle(EvasObject parent) { // focus dummy _handle = Interop.Elementary.elm_layout_add((IntPtr)parent); Interop.Elementary.elm_layout_theme_set(_handle, "layout", "elm_widget", "default"); Interop.Elementary.elm_object_focus_allow_set(_handle, true); IntPtr evas = Interop.Evas.evas_object_evas_get(parent); _realHandle = Interop.ChromiumEwk.ewk_view_add(evas); Interop.Elementary.elm_object_part_content_set(_handle, "elm.swallow.content", _realHandle); return _handle; } private void InitializeSmartEvent() { // focus dummy _focusIn = new SmartEvent(this, "focused"); _focusOut = new SmartEvent(this, "unfocused"); _focusIn.On += (s, e) => { ((WebView)s).SetFocus(true); }; _focusOut.On += (s, e) => { ((WebView)s).SetFocus(false); }; _loadStarted = new SmartEvent(this, _realHandle, "load,started"); _loadFinished = new SmartEvent(this, _realHandle, "load,finished"); _loadError = new SmartEvent(this, _realHandle, "load,error", SmartCallbackLoadErrorArgs.CreateFromSmartEvent); _titleChanged = new SmartEvent(this, _realHandle, "title,changed", SmartCallbackArgs.CreateFromSmartEvent); _urlChanged = new SmartEvent(this, _realHandle, "url,changed", SmartCallbackArgs.CreateFromSmartEvent); _loadStarted.On += (s, e) => { LoadStarted?.Invoke(this, EventArgs.Empty); }; _loadFinished.On += (s, e) => { LoadFinished?.Invoke(this, EventArgs.Empty); }; _loadError.On += (s, e) => { LoadError?.Invoke(this, e); }; _titleChanged.On += (s, e) => { TitleChanged?.Invoke(this, e); }; _urlChanged.On += (s, e) => { UrlChanged?.Invoke(this, e); }; } } }