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;
21 using System.ComponentModel;
23 namespace Tizen.WebView
26 /// Enumeration values used to specify search options.
28 /// <since_tizen> 6 </since_tizen>
30 public enum FindOption
33 /// No search flags, this means a case sensitive, no wrap, forward only search.
37 /// Case insensitive search.
39 CaseInsensitive = 1 << 0,
41 /// Search text only at the beginning of the words.
45 /// Treat capital letters in the middle of words as word start.
47 TreatMedialCapitalAsWordStart = 1 << 2,
53 /// If not present the search stops at the end of the document.
63 ShowIndicator = 1 << 6,
67 ShowHighlight = 1 << 7,
71 /// Enumeration for Http Method.
73 /// <since_tizen> 6 </since_tizen>
74 public enum HttpMethod
99 /// Enumeration for Orientation of the device.
101 /// <since_tizen> 6 </since_tizen>
102 public enum Orientation
105 /// 0 degrees when the device is oriented to natural position.
109 /// -90 degrees when it's left side is at the top.
113 /// 90 degrees when it's right side is at the top.
117 /// 180 degrees when it is upside down.
123 /// A view used to render the web contents.
125 /// <since_tizen> 4 </since_tizen>
126 public class WebView : EvasObject
128 private static IDictionary<string, JavaScriptMessageHandler> _javaScriptMessageHandlerMap = new Dictionary<string, JavaScriptMessageHandler>();
130 private IntPtr _handle;
131 private IntPtr _realHandle;
132 private Context _context;
133 private Settings _settings;
136 private SmartEvent _focusIn;
137 private SmartEvent _focusOut;
140 private SmartEvent _loadStarted;
141 private SmartEvent _loadFinished;
142 private SmartEvent<SmartCallbackLoadErrorArgs> _loadError;
143 private SmartEvent<SmartCallbackArgs> _titleChanged;
144 private SmartEvent<SmartCallbackArgs> _urlChanged;
145 private SmartEvent<NavigationPolicyEventArgs> _policyNavigationDecide;
146 private SmartEvent<NewWindowPolicyEventArgs> _policyNewWindowDecide;
147 private SmartEvent<ResponsePolicyEventArgs> _policyResponseDecide;
149 private SmartEvent<ContextMenuItemEventArgs> _contextMenuItemSelected;
150 private SmartEvent<ContextMenuCustomizeEventArgs> _contextMenuCustomize;
152 private ContextMenuCustomize _contextMenuCustomizeDelegate;
155 /// Event that occurs when the load is started.
157 /// <since_tizen> 4 </since_tizen>
158 public event EventHandler LoadStarted;
161 /// Event that occurs when the load is finished.
163 /// <since_tizen> 4 </since_tizen>
164 public event EventHandler LoadFinished;
167 /// Event that occurs when the load throws an error.
169 /// <since_tizen> 4 </since_tizen>
170 public event EventHandler<SmartCallbackLoadErrorArgs> LoadError;
173 /// Event that occurs when the title of the main frame is changed.
175 /// <since_tizen> 4 </since_tizen>
176 public event EventHandler<SmartCallbackArgs> TitleChanged;
179 /// Event that occurs when the URL of the main frame is changed.
181 /// <since_tizen> 4 </since_tizen>
182 public event EventHandler<SmartCallbackArgs> UrlChanged;
185 /// Event that occurs when the policy navigation is decided.
187 /// <since_tizen> 6 </since_tizen>
188 public event EventHandler<NavigationPolicyEventArgs> NavigationPolicyDecideRequested;
191 /// Event that occurs when the policy new window is decided.
193 /// <since_tizen> 6 </since_tizen>
194 public event EventHandler<NewWindowPolicyEventArgs> NewWindowPolicyDecideRequested;
197 /// Event that occurs when the policy response is decided.
199 /// <since_tizen> 6 </since_tizen>
200 public event EventHandler<ResponsePolicyEventArgs> ResponsePolicyDecideRequested;
203 /// Event that occurs when the context menu item selected.
205 /// <since_tizen> 6 </since_tizen>
206 public event EventHandler<ContextMenuItemEventArgs> ContextMenuItemSelected;
209 /// The delegate is invoked when context menu customization is needed.
211 /// <param name="menu">The instance of ContextMenu.</param>
212 /// <since_tizen> 6 </since_tizen>
213 public delegate void ContextMenuCustomize(ContextMenu menu);
217 /// Current URL of the main frame.
219 /// <since_tizen> 4 </since_tizen>
224 return Interop.ChromiumEwk.ewk_view_url_get(_realHandle);
229 /// Current title of the main frame.
231 /// <since_tizen> 4 </since_tizen>
236 return Interop.ChromiumEwk.ewk_view_title_get(_realHandle);
241 /// Current user agent string of this view.
243 /// <since_tizen> 4 </since_tizen>
244 public string UserAgent
248 return Interop.ChromiumEwk.ewk_view_user_agent_get(_realHandle);
253 Interop.ChromiumEwk.ewk_view_user_agent_set(_realHandle, value);
258 /// Whether a view has the focus.
260 /// <since_tizen> 4 </since_tizen>
265 return Interop.ChromiumEwk.ewk_view_focus_get(_realHandle);
270 /// Creates a WebView object.
272 /// <param name="parent">Parent object of the WebView.</param>
273 /// <since_tizen> 4 </since_tizen>
274 public WebView(EvasObject parent) : base(parent)
276 InitializeSmartEvent();
280 /// Gets the context object of this view.
282 /// <returns>The context object of this view.</returns>
283 /// <since_tizen> 4 </since_tizen>
284 public Context GetContext()
286 if (_context == null)
288 IntPtr contextHandle = Interop.ChromiumEwk.ewk_view_context_get(_realHandle);
289 if (contextHandle == IntPtr.Zero)
293 _context = new Context(contextHandle);
299 /// Gets the settings object of this view.
301 /// <returns>The settings object of this view.</returns>
302 /// <since_tizen> 4 </since_tizen>
303 public Settings GetSettings()
305 if (_settings == null)
307 IntPtr settingsHandle = Interop.ChromiumEwk.ewk_view_settings_get(_realHandle);
308 if (settingsHandle == IntPtr.Zero)
312 _settings = new Settings(settingsHandle);
318 /// Gets the back/forward list object of this view.
320 /// <returns>The BackForward List object of this view.</returns>
321 /// <since_tizen> 6 </since_tizen>
322 public BackForwardList GetBackForwardList()
324 IntPtr backforwardlistHandle = Interop.ChromiumEwk.ewk_view_back_forward_list_get(_realHandle);
325 if (backforwardlistHandle == IntPtr.Zero)
329 return new BackForwardList(backforwardlistHandle);
333 /// Clear the back/forward list object of this view.
335 /// <since_tizen> 6 </since_tizen>
336 public void ClearBackForwardList()
338 Interop.ChromiumEwk.ewk_view_back_forward_list_clear(_realHandle);
342 /// Asks the object to load the given URL.
345 /// You can only be sure that the URL changes after UrlChanged event.
347 /// <param name="url">The uniform resource identifier to load.</param>
348 /// <since_tizen> 4 </since_tizen>
349 public void LoadUrl(string url)
351 Interop.ChromiumEwk.ewk_view_url_set(_realHandle, url);
355 /// Loads the specified HTML string as the content of the view.
357 /// <param name="html">HTML data to load.</param>
358 /// <param name="baseUrl">Base URL used for relative paths to external objects.</param>
359 /// <since_tizen> 4 </since_tizen>
360 public void LoadHtml(string html, string baseUrl)
362 Interop.ChromiumEwk.ewk_view_html_string_load(_realHandle, html, baseUrl, null);
366 /// Asks the main frame to stop loading.
368 /// <since_tizen> 4 </since_tizen>
369 public void StopLoading()
371 Interop.ChromiumEwk.ewk_view_stop(_realHandle);
375 /// Asks the main frame to reload the current document.
377 /// <since_tizen> 4 </since_tizen>
380 Interop.ChromiumEwk.ewk_view_reload(_realHandle);
384 /// Asks the main frame to navigate back in history.
386 /// <since_tizen> 4 </since_tizen>
389 Interop.ChromiumEwk.ewk_view_back(_realHandle);
393 /// Asks the main frame to navigate forward in history.
395 /// <since_tizen> 4 </since_tizen>
396 public void GoForward()
398 Interop.ChromiumEwk.ewk_view_forward(_realHandle);
402 /// Checks whether it is possible to navigate backward one item in history.
404 /// <returns>Whether it is possible to navigate backward one item in history.</returns>
405 /// <since_tizen> 4 </since_tizen>
406 public bool CanGoBack()
408 return Interop.ChromiumEwk.ewk_view_back_possible(_realHandle);
412 /// Checks whether it is possible to navigate forward one item in history.
414 /// <returns>Whether it is possible to navigate forward one item in history.</returns>
415 /// <since_tizen> 4 </since_tizen>
416 public bool CanGoForward()
418 return Interop.ChromiumEwk.ewk_view_forward_possible(_realHandle);
422 /// Injects the supplied javascript message handler into the view.
424 /// <param name="name"> The message callback.</param>
425 /// <param name="handler">The name used to expose the object in JavaScript.</param>
426 /// <returns>'true' on success, otherwise 'false'.</returns>
427 /// <since_tizen> 4 </since_tizen>
428 public bool AddJavaScriptMessageHandler(string name, JavaScriptMessageHandler handler)
430 lock (_javaScriptMessageHandlerMap)
432 if (_javaScriptMessageHandlerMap.ContainsKey(name))
436 _javaScriptMessageHandlerMap[name] = handler;
438 Interop.ChromiumEwk.ScriptMessageCallback callback = (handle, message) =>
440 JavaScriptMessage convertedMessage = new JavaScriptMessage(message);
441 lock (_javaScriptMessageHandlerMap)
443 if (_javaScriptMessageHandlerMap.ContainsKey(convertedMessage.Name))
445 _javaScriptMessageHandlerMap[convertedMessage.Name](convertedMessage);
449 if (!Interop.ChromiumEwk.ewk_view_javascript_message_handler_add(_realHandle, callback, name))
451 lock (_javaScriptMessageHandlerMap)
453 _javaScriptMessageHandlerMap.Remove(name);
461 /// Requests the execution of a given name and the result to the JavaScript runtime.
463 /// <param name="name">The name used to expose the object in JavaScript.</param>
464 /// <param name="result">The result to the JavaScript runtime.</param>
465 /// <since_tizen> 4 </since_tizen>
466 public void EvalWithResult(string name, string result)
468 Interop.ChromiumEwk.ewk_view_evaluate_javascript(_realHandle, name, result);
472 /// Requests the execution of the given script.
474 /// <param name="script">The JavaScript code string to execute.</param>
475 /// <since_tizen> 4 </since_tizen>
476 public void Eval(string script)
478 Interop.ChromiumEwk.ewk_view_script_execute(_realHandle, script, null, IntPtr.Zero);
482 /// Requests to set or unset a view as the currently focused one.
484 /// <param name="focused">'true' to set the focus on the view, 'false' to remove the focus from the view.</param>
485 /// <since_tizen> 4 </since_tizen>
486 public void SetFocus(bool focused)
488 Interop.ChromiumEwk.ewk_view_focus_set(_realHandle, focused);
492 /// Gets size of the content.
494 /// <returns> size of the coordinate.</returns>
495 /// <since_tizen> 6 </since_tizen>
496 public Size ContentsSize
501 Interop.ChromiumEwk.ewk_view_contents_size_get(_realHandle, out width, out height);
502 return new Size(width, height);
507 /// Exit full screen.
509 /// <since_tizen> 6 </since_tizen>
510 public void ExitFullscreen ()
512 Interop.ChromiumEwk.ewk_view_fullscreen_exit(_realHandle);
516 /// Gets the current load progress of the page.
518 /// <returns>'value 0.0 to 1.0' on success, otherwise '-1.0'.</returns>
519 /// <since_tizen> 6 </since_tizen>
520 public double LoadProgress
524 return Interop.ChromiumEwk.ewk_view_load_progress_get(_realHandle);
529 /// Sends the orientation of the device.
531 /// <param name="orientation">The new orientation of the device in degree.</param>
532 /// <since_tizen> 6 </since_tizen>
533 public void SendOrientation (Orientation orientation)
535 Interop.ChromiumEwk.ewk_view_orientation_send(_realHandle, orientation);
539 /// Suspends the operation associated with the view.
541 /// <since_tizen> 6 </since_tizen>
542 public void Suspend ()
544 Interop.ChromiumEwk.ewk_view_suspend(_realHandle);
548 /// Resumes the operation associated with the view.
550 /// <since_tizen> 6 </since_tizen>
551 public void Resume ()
553 Interop.ChromiumEwk.ewk_view_resume(_realHandle);
557 /// Gets the current scale factor of the page.
559 /// <since_tizen> 6 </since_tizen>
564 return Interop.ChromiumEwk.ewk_view_scale_get(_realHandle);
569 /// Sets the current scale factor of the page.
571 /// <param name="scaleFactor">A new level to set.</param>
572 /// <param name="scrollTo">The class Point object with X, Y coordinates.</param>
573 /// <since_tizen> 6 </since_tizen>
574 public void SetScale (double scaleFactor, Point scrollTo)
576 Interop.ChromiumEwk.ewk_view_scale_set(_realHandle, scaleFactor, scrollTo.X, scrollTo.Y);
580 /// Sets the current page's visibility.
582 /// <param name="enable">'true' to set on the visibility of the page, 'false' otherwise.</param>
583 /// <since_tizen> 6 </since_tizen>
584 public void SetViewVisibility (bool enable)
586 Interop.ChromiumEwk.ewk_view_visibility_set(_realHandle, enable);
590 /// Get and Sets the scroll position of the page.
592 /// <returns>The class Point object with X, Y coordinates.</returns>
593 /// <since_tizen> 6 </since_tizen>
594 public Point ScrollPosition
599 Interop.ChromiumEwk.ewk_view_scroll_pos_get(_realHandle, out p.X, out p.Y);
604 Interop.ChromiumEwk.ewk_view_scroll_set(_realHandle, value.X, value.Y);
609 /// Scrolls the webpage by the given amount.
611 /// <param name="delta">The class Point object with X, Y coordinates.</param>
612 /// <since_tizen> 6 </since_tizen>
613 public void ScrollBy (Point delta)
615 Interop.ChromiumEwk.ewk_view_scroll_by(_realHandle, delta.X, delta.Y);
619 /// Searches and highlights the given text string in the document.
621 /// <param name="text">The text to find.</param>
622 /// <param name="option">The options to find.</param>
623 /// <param name="maxMatchCount">The maximum match count to find, unlimited if 0.</param>
624 /// <since_tizen> 6 </since_tizen>
625 public void FindText (string text, FindOption option, int maxMatchCount)
627 Interop.ChromiumEwk.ewk_view_text_find(_realHandle, text, option, maxMatchCount);
631 /// Requests loading of the given request data.
633 /// <param name="url">The uniform resource identifier to load.</param>
634 /// <param name="httpMethod">The http method.</param>
635 /// <param name="httpHeaders">The http headers.</param>
636 /// <param name="httpBody">The http body data.</param>
637 /// <since_tizen> 6 </since_tizen>
638 public void SetUrlRequest (string url, HttpMethod httpMethod, IDictionary<string, string> httpHeaders, string httpBody)
640 List<IntPtr> stringHandles = new List<IntPtr>();
641 IntPtr hashHttpHeaders = Interop.Eina.eina_hash_string_small_new(IntPtr.Zero);
643 foreach (KeyValuePair<string, string> entry in httpHeaders)
645 IntPtr keyHandle = Marshal.StringToHGlobalAnsi(entry.Key);
646 IntPtr valueHandle = Marshal.StringToHGlobalAnsi(entry.Value);
647 Interop.Eina.eina_hash_add(hashHttpHeaders, keyHandle, valueHandle);
648 stringHandles.Add(keyHandle);
649 stringHandles.Add(valueHandle);
651 Interop.ChromiumEwk.ewk_view_url_request_set(_realHandle, url, httpMethod, hashHttpHeaders, httpBody);
653 foreach(IntPtr handle in stringHandles)
655 Marshal.FreeHGlobal(handle);
660 /// Creates a widget handle.
662 /// <param name="parent">Parent EvasObject.</param>
663 /// <returns>IntPtr of the widget handle.</returns>
664 /// <since_tizen> 4 </since_tizen>
665 protected override IntPtr CreateHandle(EvasObject parent)
668 _handle = Interop.Elementary.elm_layout_add((IntPtr)parent);
669 Interop.Elementary.elm_layout_theme_set(_handle, "layout", "elm_widget", "default");
670 Interop.Elementary.elm_object_focus_allow_set(_handle, true);
672 IntPtr evas = Interop.Evas.evas_object_evas_get(parent);
673 _realHandle = Interop.ChromiumEwk.ewk_view_add(evas);
674 Interop.Elementary.elm_object_part_content_set(_handle, "elm.swallow.content", _realHandle);
680 /// Sets the delegate for context menu customization.
682 /// <param name="contextMenuCustomizeDelegate">The delegate for context menu customization.</param>
683 /// <since_tizen> 6 </since_tizen>
684 public void SetContextMenuCustomizeDelegate(ContextMenuCustomize contextMenuCustomizeDelegate)
686 _contextMenuCustomizeDelegate = contextMenuCustomizeDelegate;
689 private void InitializeSmartEvent()
692 _focusIn = new SmartEvent(this, "focused");
693 _focusOut = new SmartEvent(this, "unfocused");
695 _focusIn.On += (s, e) => { ((WebView)s).SetFocus(true); };
696 _focusOut.On += (s, e) => { ((WebView)s).SetFocus(false); };
698 _loadStarted = new SmartEvent(this, _realHandle, "load,started");
699 _loadFinished = new SmartEvent(this, _realHandle, "load,finished");
700 _loadError = new SmartEvent<SmartCallbackLoadErrorArgs>(this, _realHandle, "load,error", SmartCallbackLoadErrorArgs.CreateFromSmartEvent);
701 _titleChanged = new SmartEvent<SmartCallbackArgs>(this, _realHandle, "title,changed", SmartCallbackArgs.CreateFromSmartEvent);
702 _urlChanged = new SmartEvent<SmartCallbackArgs>(this, _realHandle, "url,changed", SmartCallbackArgs.CreateFromSmartEvent);
703 _contextMenuCustomize = new SmartEvent<ContextMenuCustomizeEventArgs>(this, _realHandle, "contextmenu,customize", ContextMenuCustomizeEventArgs.CreateFromSmartEvent);
704 _contextMenuItemSelected = new SmartEvent<ContextMenuItemEventArgs>(this, _realHandle, "contextmenu,selected", ContextMenuItemEventArgs.CreateFromSmartEvent);
705 _policyNavigationDecide = new SmartEvent<NavigationPolicyEventArgs>(this, _realHandle, "policy,navigation,decide", NavigationPolicyEventArgs.CreateFromSmartEvent);
706 _policyNewWindowDecide = new SmartEvent<NewWindowPolicyEventArgs>(this, _realHandle, "policy,newwindow,decide", NewWindowPolicyEventArgs.CreateFromSmartEvent);
707 _policyResponseDecide = new SmartEvent<ResponsePolicyEventArgs>(this, _realHandle, "policy,response,decide", ResponsePolicyEventArgs.CreateFromSmartEvent);
709 _loadStarted.On += (s, e) => { LoadStarted?.Invoke(this, EventArgs.Empty); };
710 _loadFinished.On += (s, e) => { LoadFinished?.Invoke(this, EventArgs.Empty); };
711 _loadError.On += (s, e) => { LoadError?.Invoke(this, e); };
712 _titleChanged.On += (s, e) => { TitleChanged?.Invoke(this, e); };
713 _urlChanged.On += (s, e) => { UrlChanged?.Invoke(this, e); };
714 _policyNavigationDecide.On += (s, e) => { NavigationPolicyDecideRequested?.Invoke(this, e); };
715 _policyNewWindowDecide.On += (s, e) => { NewWindowPolicyDecideRequested?.Invoke(this, e); };
716 _policyResponseDecide.On += (s, e) => { ResponsePolicyDecideRequested?.Invoke(this, e); };
717 _contextMenuItemSelected.On += (s, e) => { ContextMenuItemSelected?.Invoke(this, e); };
718 _contextMenuCustomize.On += (s, e) => { _contextMenuCustomizeDelegate?.Invoke(e.Menu); };