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