2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Collections.Generic;
20 using System.Runtime.InteropServices;
22 namespace Tizen.WebView
25 /// A view used to render the web contents.
27 /// <since_tizen> 4 </since_tizen>
28 public class WebView : EvasObject
30 private static IDictionary<string, JavaScriptMessageHandler> _javaScriptMessageHandlerMap = new Dictionary<string, JavaScriptMessageHandler>();
32 private IntPtr _handle;
33 private IntPtr _realHandle;
34 private Context _context;
35 private Settings _settings;
38 private SmartEvent _focusIn;
39 private SmartEvent _focusOut;
42 private SmartEvent _loadStarted;
43 private SmartEvent _loadFinished;
44 private SmartEvent<SmartCallbackLoadErrorArgs> _loadError;
45 private SmartEvent<SmartCallbackArgs> _titleChanged;
46 private SmartEvent<SmartCallbackArgs> _urlChanged;
47 private SmartEvent<NavigationPolicyEventArgs> _policyNavigationDecide;
48 private SmartEvent<NewWindowPolicyEventArgs> _policyNewWindowDecide;
49 private SmartEvent<ResponsePolicyEventArgs> _policyResponseDecide;
51 private SmartEvent<ContextMenuItemEventArgs> _contextMenuItemSelected;
52 private SmartEvent<ContextMenuCustomizeEventArgs> _contextMenuCustomize;
54 private ContextMenuCustomize _contextMenuCustomizeDelegate;
57 /// Event that occurs when the load is started.
59 /// <since_tizen> 4 </since_tizen>
60 public event EventHandler LoadStarted;
63 /// Event that occurs when the load is finished.
65 /// <since_tizen> 4 </since_tizen>
66 public event EventHandler LoadFinished;
69 /// Event that occurs when the load throws an error.
71 /// <since_tizen> 4 </since_tizen>
72 public event EventHandler<SmartCallbackLoadErrorArgs> LoadError;
75 /// Event that occurs when the title of the main frame is changed.
77 /// <since_tizen> 4 </since_tizen>
78 public event EventHandler<SmartCallbackArgs> TitleChanged;
81 /// Event that occurs when the URL of the main frame is changed.
83 /// <since_tizen> 4 </since_tizen>
84 public event EventHandler<SmartCallbackArgs> UrlChanged;
88 /// Event that occurs when the policy navigation is decided.
90 /// <since_tizen> 6 </since_tizen>
91 public event EventHandler<NavigationPolicyEventArgs> NavigationPolicyDecideRequested;
94 /// Event that occurs when the policy new window is decided.
96 /// <since_tizen> 6 </since_tizen>
97 public event EventHandler<NewWindowPolicyEventArgs> NewWindowPolicyDecideRequested;
100 /// Event that occurs when the policy response is decided.
102 /// <since_tizen> 6 </since_tizen>
103 public event EventHandler<ResponsePolicyEventArgs> ResponsePolicyDecideRequested;
106 /// Event that occurs when the context menu item selected.
108 /// <since_tizen> 6 </since_tizen>
109 public event EventHandler<ContextMenuItemEventArgs> ContextMenuItemSelected;
111 /// The delegate is invoked when context menu customization is needed.
113 /// <param name="menu">The instance of ContextMenu.</param>
114 /// <since_tizen> 6 </since_tizen>
115 public delegate void ContextMenuCustomize(ContextMenu menu);
119 /// Current URL of the main frame.
121 /// <since_tizen> 4 </since_tizen>
126 return Interop.ChromiumEwk.ewk_view_url_get(_realHandle);
131 /// Current title of the main frame.
133 /// <since_tizen> 4 </since_tizen>
138 return Interop.ChromiumEwk.ewk_view_title_get(_realHandle);
143 /// Current user agent string of this view.
145 /// <since_tizen> 4 </since_tizen>
146 public string UserAgent
150 return Interop.ChromiumEwk.ewk_view_user_agent_get(_realHandle);
155 Interop.ChromiumEwk.ewk_view_user_agent_set(_realHandle, value);
160 /// Whether a view has the focus.
162 /// <since_tizen> 4 </since_tizen>
167 return Interop.ChromiumEwk.ewk_view_focus_get(_realHandle);
172 /// Creates a WebView object.
174 /// <param name="parent">Parent object of the WebView.</param>
175 /// <since_tizen> 4 </since_tizen>
176 public WebView(EvasObject parent) : base(parent)
178 InitializeSmartEvent();
182 /// Gets the context object of this view.
184 /// <returns>The context object of this view.</returns>
185 /// <since_tizen> 4 </since_tizen>
186 public Context GetContext()
188 if (_context == null)
190 IntPtr contextHandle = Interop.ChromiumEwk.ewk_view_context_get(_realHandle);
191 if (contextHandle == IntPtr.Zero)
195 _context = new Context(contextHandle);
201 /// Gets the settings object of this view.
203 /// <returns>The settings object of this view.</returns>
204 /// <since_tizen> 4 </since_tizen>
205 public Settings GetSettings()
207 if (_settings == null)
209 IntPtr settingsHandle = Interop.ChromiumEwk.ewk_view_settings_get(_realHandle);
210 if (settingsHandle == IntPtr.Zero)
214 _settings = new Settings(settingsHandle);
220 /// Gets the back/forward list object of this view.
222 /// <returns>The BackForward List object of this view.</returns>
223 /// <since_tizen> 6 </since_tizen>
224 public BackForwardList GetBackForwardList()
226 IntPtr backforwardlistHandle = Interop.ChromiumEwk.ewk_view_back_forward_list_get(_realHandle);
227 if (backforwardlistHandle == IntPtr.Zero)
231 return new BackForwardList(backforwardlistHandle);
235 /// Clear the back/forward list object of this view.
237 /// <since_tizen> 6 </since_tizen>
238 public void ClearBackForwardList()
240 Interop.ChromiumEwk.ewk_view_back_forward_list_clear(_realHandle);
244 /// Asks the object to load the given URL.
247 /// You can only be sure that the URL changes after UrlChanged event.
249 /// <param name="url">The uniform resource identifier to load.</param>
250 /// <since_tizen> 4 </since_tizen>
251 public void LoadUrl(string url)
253 Interop.ChromiumEwk.ewk_view_url_set(_realHandle, url);
257 /// Loads the specified HTML string as the content of the view.
259 /// <param name="html">HTML data to load.</param>
260 /// <param name="baseUrl">Base URL used for relative paths to external objects.</param>
261 /// <since_tizen> 4 </since_tizen>
262 public void LoadHtml(string html, string baseUrl)
264 Interop.ChromiumEwk.ewk_view_html_string_load(_realHandle, html, baseUrl, null);
268 /// Asks the main frame to stop loading.
270 /// <since_tizen> 4 </since_tizen>
271 public void StopLoading()
273 Interop.ChromiumEwk.ewk_view_stop(_realHandle);
277 /// Asks the main frame to reload the current document.
279 /// <since_tizen> 4 </since_tizen>
282 Interop.ChromiumEwk.ewk_view_reload(_realHandle);
286 /// Asks the main frame to navigate back in history.
288 /// <since_tizen> 4 </since_tizen>
291 Interop.ChromiumEwk.ewk_view_back(_realHandle);
295 /// Asks the main frame to navigate forward in history.
297 /// <since_tizen> 4 </since_tizen>
298 public void GoForward()
300 Interop.ChromiumEwk.ewk_view_forward(_realHandle);
304 /// Checks whether it is possible to navigate backward one item in history.
306 /// <returns>Whether it is possible to navigate backward one item in history.</returns>
307 /// <since_tizen> 4 </since_tizen>
308 public bool CanGoBack()
310 return Interop.ChromiumEwk.ewk_view_back_possible(_realHandle);
314 /// Checks whether it is possible to navigate forward one item in history.
316 /// <returns>Whether it is possible to navigate forward one item in history.</returns>
317 /// <since_tizen> 4 </since_tizen>
318 public bool CanGoForward()
320 return Interop.ChromiumEwk.ewk_view_forward_possible(_realHandle);
324 /// Injects the supplied javascript message handler into the view.
326 /// <param name="name"> The message callback.</param>
327 /// <param name="handler">The name used to expose the object in JavaScript.</param>
328 /// <returns>'true' on success, otherwise 'false'.</returns>
329 /// <since_tizen> 4 </since_tizen>
330 public bool AddJavaScriptMessageHandler(string name, JavaScriptMessageHandler handler)
332 lock (_javaScriptMessageHandlerMap)
334 if (_javaScriptMessageHandlerMap.ContainsKey(name))
338 _javaScriptMessageHandlerMap[name] = handler;
340 Interop.ChromiumEwk.ScriptMessageCallback callback = (handle, message) =>
342 JavaScriptMessage convertedMessage = new JavaScriptMessage(message);
343 lock (_javaScriptMessageHandlerMap)
345 if (_javaScriptMessageHandlerMap.ContainsKey(convertedMessage.Name))
347 _javaScriptMessageHandlerMap[convertedMessage.Name](convertedMessage);
351 if (!Interop.ChromiumEwk.ewk_view_javascript_message_handler_add(_realHandle, callback, name))
353 lock (_javaScriptMessageHandlerMap)
355 _javaScriptMessageHandlerMap.Remove(name);
363 /// Requests the execution of a given name and the result to the JavaScript runtime.
365 /// <param name="name">The name used to expose the object in JavaScript.</param>
366 /// <param name="result">The result to the JavaScript runtime.</param>
367 /// <since_tizen> 4 </since_tizen>
368 public void EvalWithResult(string name, string result)
370 Interop.ChromiumEwk.ewk_view_evaluate_javascript(_realHandle, name, result);
374 /// Requests the execution of the given script.
376 /// <param name="script">The JavaScript code string to execute.</param>
377 /// <since_tizen> 4 </since_tizen>
378 public void Eval(string script)
380 Interop.ChromiumEwk.ewk_view_script_execute(_realHandle, script, null, IntPtr.Zero);
384 /// Requests to set or unset a view as the currently focused one.
386 /// <param name="focused">'true' to set the focus on the view, 'false' to remove the focus from the view.</param>
387 /// <since_tizen> 4 </since_tizen>
388 public void SetFocus(bool focused)
390 Interop.ChromiumEwk.ewk_view_focus_set(_realHandle, focused);
394 /// Creates a widget handle.
396 /// <param name="parent">Parent EvasObject.</param>
397 /// <returns>IntPtr of the widget handle.</returns>
398 /// <since_tizen> 4 </since_tizen>
399 protected override IntPtr CreateHandle(EvasObject parent)
402 _handle = Interop.Elementary.elm_layout_add((IntPtr)parent);
403 Interop.Elementary.elm_layout_theme_set(_handle, "layout", "elm_widget", "default");
404 Interop.Elementary.elm_object_focus_allow_set(_handle, true);
406 IntPtr evas = Interop.Evas.evas_object_evas_get(parent);
407 _realHandle = Interop.ChromiumEwk.ewk_view_add(evas);
408 Interop.Elementary.elm_object_part_content_set(_handle, "elm.swallow.content", _realHandle);
414 /// Sets the delegate for context menu customization.
416 /// <param name="contextMenuCustomizeDelegate">The delegate for context menu customization.</param>
417 /// <since_tizen> 6 </since_tizen>
418 public void SetContextMenuCustomizeDelegate(ContextMenuCustomize contextMenuCustomizeDelegate)
420 _contextMenuCustomizeDelegate = contextMenuCustomizeDelegate;
423 private void InitializeSmartEvent()
426 _focusIn = new SmartEvent(this, "focused");
427 _focusOut = new SmartEvent(this, "unfocused");
429 _focusIn.On += (s, e) => { ((WebView)s).SetFocus(true); };
430 _focusOut.On += (s, e) => { ((WebView)s).SetFocus(false); };
432 _loadStarted = new SmartEvent(this, _realHandle, "load,started");
433 _loadFinished = new SmartEvent(this, _realHandle, "load,finished");
434 _loadError = new SmartEvent<SmartCallbackLoadErrorArgs>(this, _realHandle, "load,error", SmartCallbackLoadErrorArgs.CreateFromSmartEvent);
435 _titleChanged = new SmartEvent<SmartCallbackArgs>(this, _realHandle, "title,changed", SmartCallbackArgs.CreateFromSmartEvent);
436 _urlChanged = new SmartEvent<SmartCallbackArgs>(this, _realHandle, "url,changed", SmartCallbackArgs.CreateFromSmartEvent);
437 _contextMenuCustomize = new SmartEvent<ContextMenuCustomizeEventArgs>(this, _realHandle, "contextmenu,customize", ContextMenuCustomizeEventArgs.CreateFromSmartEvent);
438 _contextMenuItemSelected = new SmartEvent<ContextMenuItemEventArgs>(this, _realHandle, "contextmenu,selected", ContextMenuItemEventArgs.CreateFromSmartEvent);
439 _policyNavigationDecide = new SmartEvent<NavigationPolicyEventArgs>(this, _realHandle, "policy,navigation,decide", NavigationPolicyEventArgs.CreateFromSmartEvent);
440 _policyNewWindowDecide = new SmartEvent<NewWindowPolicyEventArgs>(this, _realHandle, "policy,newwindow,decide", NewWindowPolicyEventArgs.CreateFromSmartEvent);
441 _policyResponseDecide = new SmartEvent<ResponsePolicyEventArgs>(this, _realHandle, "policy,response,decide", ResponsePolicyEventArgs.CreateFromSmartEvent);
443 _loadStarted.On += (s, e) => { LoadStarted?.Invoke(this, EventArgs.Empty); };
444 _loadFinished.On += (s, e) => { LoadFinished?.Invoke(this, EventArgs.Empty); };
445 _loadError.On += (s, e) => { LoadError?.Invoke(this, e); };
446 _titleChanged.On += (s, e) => { TitleChanged?.Invoke(this, e); };
447 _urlChanged.On += (s, e) => { UrlChanged?.Invoke(this, e); };
448 _policyNavigationDecide.On += (s, e) => { NavigationPolicyDecideRequested?.Invoke(this, e); };
449 _policyNewWindowDecide.On += (s, e) => { NewWindowPolicyDecideRequested?.Invoke(this, e); };
450 _policyResponseDecide.On += (s, e) => { ResponsePolicyDecideRequested?.Invoke(this, e); };
451 _contextMenuItemSelected.On += (s, e) => { ContextMenuItemSelected?.Invoke(this, e); };
452 _contextMenuCustomize.On += (s, e) => { _contextMenuCustomizeDelegate?.Invoke(e.Menu); };