Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.WebView / Tizen.WebView / WebView.cs
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 using ElmSharp;
18 using System;
19 using System.Collections.Generic;
20 using System.Runtime.InteropServices;
21
22 namespace Tizen.WebView
23 {
24     /// <summary>
25     /// A view used to render web contents.
26     /// </summary>
27     public class WebView: EvasObject
28     {
29         private static IDictionary<string, JavaScriptMessageHandler> _javaScriptMessageHandlerMap = new Dictionary<string, JavaScriptMessageHandler>();
30
31         private IntPtr _handle;
32         private IntPtr _realHandle;
33         private Context _context;
34         private Settings _settings;
35
36         // focus dummy
37         private SmartEvent _focusIn;
38         private SmartEvent _focusOut;
39
40         // Smart events
41         private SmartEvent _loadStarted;
42         private SmartEvent _loadFinished;
43         private SmartEvent<SmartCallbackLoadErrorArgs> _loadError;
44         private SmartEvent<SmartCallbackArgs> _titleChanged;
45         private SmartEvent<SmartCallbackArgs> _urlChanged;
46
47
48
49         /// <summary>
50         /// Event that occurs when load started.
51         /// </summary>
52         public event EventHandler LoadStarted;
53
54         /// <summary>
55         /// Event that occurs when load finished.
56         /// </summary>
57         public event EventHandler LoadFinished;
58
59         /// <summary>
60         /// Event that occurs when load error.
61         /// </summary>
62         public event EventHandler<SmartCallbackLoadErrorArgs> LoadError;
63
64         /// <summary>
65         /// Event that occurs when title of main frame was changed.
66         /// </summary>
67         public event EventHandler<SmartCallbackArgs> TitleChanged;
68
69         /// <summary>
70         /// Event that occurs when URL of main frame was changed.
71         /// </summary>
72         public event EventHandler<SmartCallbackArgs> UrlChanged;
73
74         /// <summary>
75         /// Current URL of the main frame.
76         /// </summary>
77         public string Url
78         {
79             get
80             {
81                 return Interop.ChromiumEwk.ewk_view_url_get(_realHandle);
82             }
83         }
84
85         /// <summary>
86         /// Current title of the main frame.
87         /// </summary>
88         public string Title
89         {
90             get
91             {
92                 return Interop.ChromiumEwk.ewk_view_title_get(_realHandle);
93             }
94         }
95
96         /// <summary>
97         /// Current user agent string of this view.
98         /// </summary>
99         public string UserAgent
100         {
101             get
102             {
103                 return Interop.ChromiumEwk.ewk_view_user_agent_get(_realHandle);
104             }
105
106             set
107             {
108                 Interop.ChromiumEwk.ewk_view_user_agent_set(_realHandle, value);
109             }
110         }
111
112         /// <summary>
113         /// Whether a view has the focus.
114         /// </summary>
115         public bool HasFocus
116         {
117             get
118             {
119                 return Interop.ChromiumEwk.ewk_view_focus_get(_realHandle);
120             }
121         }
122
123         /// <summary>
124         /// Create a WebView object.
125         /// </summary>
126         /// <param name="parent">Parent object of WebView</param>
127         public WebView(EvasObject parent) : base(parent)
128         {
129             InitializeSmartEvent();
130         }
131
132         /// <summary>
133         /// Gets the Context object of this view.
134         /// </summary>
135         /// <returns>The Context object of this view</returns>
136         public Context GetContext()
137         {
138             if (_context == null)
139             {
140                 IntPtr contextHandle = Interop.ChromiumEwk.ewk_view_context_get(_realHandle);
141                 if (contextHandle == IntPtr.Zero)
142                 {
143                     return null;
144                 }
145                 _context = new Context(contextHandle);
146             }
147             return _context;
148         }
149
150         /// <summary>
151         /// Gets the Settings object of this view.
152         /// </summary>
153         /// <returns>The Settings object of this view</returns>
154         public Settings GetSettings()
155         {
156             if (_settings == null)
157             {
158                 IntPtr settingsHandle = Interop.ChromiumEwk.ewk_view_settings_get(_realHandle);
159                 if (settingsHandle == IntPtr.Zero)
160                 {
161                     return null;
162                 }
163                 _settings = new Settings(settingsHandle);
164             }
165             return _settings;
166         }
167
168         /// <summary>
169         /// Asks the object to load the given URL.
170         /// </summary>
171         /// <remarks>
172         /// You can only be sure that url changed after UrlChanged event.
173         /// </remarks>
174         /// <param name="url">The uniform resource identifier to load</param>
175         public void LoadUrl(string url)
176         {
177             Interop.ChromiumEwk.ewk_view_url_set(_realHandle, url);
178         }
179
180         /// <summary>
181         /// Loads the specified html string as the content of the view.
182         /// </summary>
183         /// <param name="html">HTML data to load</param>
184         /// <param name="baseUrl">Base URL used for relative paths to external objects</param>
185         public void LoadHtml(string html, string baseUrl)
186         {
187             Interop.ChromiumEwk.ewk_view_html_string_load(_realHandle, html, baseUrl, null);
188         }
189
190         /// <summary>
191         /// Asks the main frame to stop loading.
192         /// </summary>
193         public void StopLoading()
194         {
195             Interop.ChromiumEwk.ewk_view_stop(_realHandle);
196         }
197
198         /// <summary>
199         /// Asks the main frame to reload the current document.
200         /// </summary>
201         public void Reload()
202         {
203             Interop.ChromiumEwk.ewk_view_reload(_realHandle);
204         }
205
206         /// <summary>
207         /// Asks the main frame to navigate back in history.
208         /// </summary>
209         public void GoBack()
210         {
211             Interop.ChromiumEwk.ewk_view_back(_realHandle);
212         }
213
214         /// <summary>
215         /// Asks the main frame to navigate forward in history.
216         /// </summary>
217         public void GoForward()
218         {
219             Interop.ChromiumEwk.ewk_view_forward(_realHandle);
220         }
221
222         /// <summary>
223         /// Checks whether it is possible to navigate backwards one item in history.
224         /// </summary>
225         /// <returns>Whether it is possible to navigate backwards one item in history</returns>
226         public bool CanGoBack()
227         {
228             return Interop.ChromiumEwk.ewk_view_back_possible(_realHandle);
229         }
230
231         /// <summary>
232         /// Checks whether it is possible to navigate forwards one item in history.
233         /// </summary>
234         /// <returns>Whether it is possible to navigate forwards one item in history</returns>
235         public bool CanGoForward()
236         {
237             return Interop.ChromiumEwk.ewk_view_forward_possible(_realHandle);
238         }
239
240         /// <summary>
241         /// Injects the supplied javascript message handler into the view.
242         /// </summary>
243         /// <param name="name"> The message callback</param>
244         /// <param name="handler">The name used to expose the object in JavaScript</param>
245         /// <returns>'true' on success, otherwise 'false'</returns>
246         public bool AddJavaScriptMessageHandler(string name, JavaScriptMessageHandler handler)
247         {
248             lock (_javaScriptMessageHandlerMap)
249             {
250                 if (_javaScriptMessageHandlerMap.ContainsKey(name))
251                 {
252                     return false;
253                 }
254                 _javaScriptMessageHandlerMap[name] = handler;
255             }
256             Interop.ChromiumEwk.ScriptMessageCallback callback = (handle, message) =>
257             {
258                 JavaScriptMessage convertedMessage = new JavaScriptMessage(message);
259                 lock (_javaScriptMessageHandlerMap)
260                 {
261                     if (_javaScriptMessageHandlerMap.ContainsKey(convertedMessage.Name))
262                     {
263                         _javaScriptMessageHandlerMap[convertedMessage.Name](convertedMessage);
264                     }
265                 }
266             };
267             if (!Interop.ChromiumEwk.ewk_view_javascript_message_handler_add(_realHandle, callback, name))
268             {
269                 lock (_javaScriptMessageHandlerMap)
270                 {
271                     _javaScriptMessageHandlerMap.Remove(name);
272                     return false;
273                 }
274             }
275             return true;
276         }
277
278         /// <summary>
279         /// Requests the execution of given name and result to the JavaScript runtime.
280         /// </summary>
281         /// <param name="name">The name used to expose the object in JavaScript</param>
282         /// <param name="result">The result to the JavaScript runtime</param>
283         public void EvalWithResult(string name, string result)
284         {
285             Interop.ChromiumEwk.ewk_view_evaluate_javascript(_realHandle, name, result);
286         }
287
288         /// <summary>
289         /// Requests the execution of the given script.
290         /// </summary>
291         /// <param name="script">The JavaScript code string to execute</param>
292         public void Eval(string script)
293         {
294             Interop.ChromiumEwk.ewk_view_script_execute(_realHandle, script, null, IntPtr.Zero);
295         }
296
297         /// <summary>
298         /// Requests to set or unset a view as the currently focused one.
299         /// </summary>
300         /// <param name="focused">'true' to set the focus on the view, 'false' to remove the focus from the view</param>
301         public void SetFocus(bool focused)
302         {
303             Interop.ChromiumEwk.ewk_view_focus_set(_realHandle, focused);
304         }
305
306         protected override IntPtr CreateHandle(EvasObject parent)
307         {
308             // focus dummy
309             _handle = Interop.Elementary.elm_layout_add((IntPtr)parent);
310             Interop.Elementary.elm_layout_theme_set(_handle, "layout", "elm_widget", "default");
311             Interop.Elementary.elm_object_focus_allow_set(_handle, true);
312
313             IntPtr evas = Interop.Evas.evas_object_evas_get(parent);
314             _realHandle = Interop.ChromiumEwk.ewk_view_add(evas);
315             Interop.Elementary.elm_object_part_content_set(_handle, "elm.swallow.content", _realHandle);
316
317             return _handle;
318         }
319
320         private void InitializeSmartEvent()
321         {
322             // focus dummy
323             _focusIn = new SmartEvent(this, "focused");
324             _focusOut = new SmartEvent(this, "unfocused");
325
326             _focusIn.On += (s, e) => { ((WebView)s).SetFocus(true); };
327             _focusOut.On += (s, e) => { ((WebView)s).SetFocus(false); };
328
329             _loadStarted = new SmartEvent(this, _realHandle, "load,started");
330             _loadFinished = new SmartEvent(this, _realHandle, "load,finished");
331             _loadError = new SmartEvent<SmartCallbackLoadErrorArgs>(this, _realHandle, "load,error", SmartCallbackLoadErrorArgs.CreateFromSmartEvent);
332             _titleChanged = new SmartEvent<SmartCallbackArgs>(this, _realHandle, "title,changed", SmartCallbackArgs.CreateFromSmartEvent);
333             _urlChanged = new SmartEvent<SmartCallbackArgs>(this, _realHandle, "url,changed", SmartCallbackArgs.CreateFromSmartEvent);
334
335             _loadStarted.On += (s, e) => { LoadStarted?.Invoke(this, EventArgs.Empty); };
336             _loadFinished.On += (s, e) => { LoadFinished?.Invoke(this, EventArgs.Empty); };
337             _loadError.On += (s, e) => { LoadError?.Invoke(this, e); };
338             _titleChanged.On += (s, e) => { TitleChanged?.Invoke(this, e); };
339             _urlChanged.On += (s, e) => { UrlChanged?.Invoke(this, e); };
340         }
341     }
342 }