Delete ewk_view on WebView was deleted
[platform/framework/web/crosswalk-tizen.git] / src / runtime / web_view.cc
1 // Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "runtime/web_view.h"
6
7 #include <ewk_chromium.h>
8 #include <functional>
9
10 #include "runtime/native_window.h"
11
12 namespace wrt {
13
14 namespace {
15
16 // TODO(sngn.lee) : It should be declare in common header
17 const char* kKeyNameBack = "back";
18 const char* kKeyNameMenu = "menu";
19
20 static int ToWebRotation(int r) {
21   switch (r) {
22     case 0:
23     case 180:
24       return r;
25     case 90:
26       return -90;
27     case 270:
28       return 90;
29   }
30   return r;
31 }
32
33 }  // namespace
34
35
36 WebView::WebView(NativeWindow* window, Ewk_Context* context)
37     : window_(window),
38       context_(context),
39       ewk_view_(NULL),
40       listener_(NULL) {
41   Initialize();
42 }
43
44 WebView::~WebView() {
45   window_->RemoveRotationHandler(rotation_handler_id_);
46   evas_object_del(ewk_view_);
47 }
48
49 void WebView::LoadUrl(const std::string& url) {
50   ewk_view_url_set(ewk_view_, url.c_str());
51 }
52
53 void WebView::Suspend() {
54   // suspend webview
55   ewk_view_suspend(ewk_view_);
56 }
57
58 void WebView::Resume() {
59   // resume webview
60   ewk_view_resume(ewk_view_);
61 }
62
63 void WebView::Reload() {
64   ewk_view_reload(ewk_view_);
65 }
66
67 void WebView::SetVisibility(bool show) {
68   ewk_view_visibility_set(ewk_view_, show ? EINA_TRUE : EINA_FALSE);
69 }
70
71
72 bool WebView::EvalJavascript(const std::string& script) {
73   return ewk_view_script_execute(ewk_view_, script.c_str(), NULL, NULL);
74 }
75
76 void WebView::Initialize() {
77   ewk_view_ = ewk_view_add_with_context(window_->evas_object(), context_);
78
79   // TODO(sngn.lee): To be implemented - orientation lock
80
81
82   auto key_callback = [](void* user_data,
83                          Evas_Object* /*obj*/,
84                          void* event_info) -> void {
85     WebView* self = static_cast<WebView*>(user_data);
86     Ea_Callback_Type key = static_cast<Ea_Callback_Type>(
87                               reinterpret_cast<int>(event_info));
88     self->OnKeyEvent(key);
89   };
90   ea_object_event_callback_add(ewk_view_,
91                                EA_CALLBACK_BACK,
92                                key_callback,
93                                this);
94   ea_object_event_callback_add(ewk_view_,
95                                EA_CALLBACK_MORE,
96                                key_callback,
97                                this);
98
99
100   // load statred callback
101   auto loadstart_callback = [](void* user_data,
102                                Evas_Object* /*obj*/,
103                                void*) {
104     WebView* self = static_cast<WebView*>(user_data);
105     if (self->listener_)
106       self->listener_->OnLoadStart(self);
107   };
108   evas_object_smart_callback_add(ewk_view_,
109                                  "load,started",
110                                  loadstart_callback,
111                                  this);
112   // load finished callback
113   auto loadfinished_callback = [](void* user_data,
114                                   Evas_Object*,
115                                   void*) {
116     WebView* self = static_cast<WebView*>(user_data);
117     if (self->listener_)
118       self->listener_->OnLoadFinished(self);
119   };
120   evas_object_smart_callback_add(ewk_view_,
121                                  "load,finished",
122                                  loadfinished_callback,
123                                  this);
124
125   // load progress callback
126   auto loadprogress_callback = [](void* user_data,
127                                   Evas_Object*,
128                                   void* event_info) {
129     WebView* self = static_cast<WebView*>(user_data);
130     double* progress = static_cast<double*>(event_info);
131     if (self->listener_)
132       self->listener_->OnLoadProgress(self, *progress);
133   };
134   evas_object_smart_callback_add(ewk_view_,
135                                  "load,progress",
136                                  loadprogress_callback,
137                                  this);
138   // rendered callback
139   auto rendered_callback = [](void* user_data,
140                               Evas_Object*,
141                               void*) {
142     WebView* self = static_cast<WebView*>(user_data);
143     if (self->listener_)
144       self->listener_->OnRendered(self);
145   };
146   evas_object_smart_callback_add(ewk_view_,
147                                  "frame,rendered",
148                                  rendered_callback,
149                                  this);
150
151   // "policy,navigation,decide"
152   auto navigation_decide_callback = [](void* user_data,
153                                        Evas_Object*,
154                                        void* event_info) {
155     WebView* self = static_cast<WebView*>(user_data);
156     Ewk_Policy_Decision* policy =
157             static_cast<Ewk_Policy_Decision*>(event_info);
158     const char* url = ewk_policy_decision_url_get(policy);
159
160     if (self->listener_) {
161       if (self->listener_->OnDidNavigation(self, url))
162         ewk_policy_decision_use(policy);
163       else
164         ewk_policy_decision_ignore(policy);
165     } else {
166       ewk_policy_decision_use(policy);
167     }
168   };
169   evas_object_smart_callback_add(ewk_view_,
170                                  "policy,navigation,decide",
171                                  navigation_decide_callback,
172                                  this);
173
174   // policy,newwindow,decide
175   auto newwindow_decide_callback = [](void* user_data,
176                                       Evas_Object*,
177                                       void* event_info) {
178     WebView* self = static_cast<WebView*>(user_data);
179     Ewk_Policy_Decision* policy =
180             static_cast<Ewk_Policy_Decision*>(event_info);
181
182     const char* url = ewk_policy_decision_url_get(policy);
183
184     if (self->listener_) {
185       if (self->listener_->OnDidNavigation(self, url) &&
186          self->listener_->OnDidOpenWindow(self, url)) {
187          ewk_policy_decision_use(policy);
188       } else {
189         ewk_policy_decision_ignore(policy);
190       }
191     } else {
192       ewk_policy_decision_use(policy);
193     }
194   };
195   evas_object_smart_callback_add(ewk_view_,
196                                  "policy,newwindow,decide",
197                                  newwindow_decide_callback,
198                                  this);
199
200   // callback for database quota exceeded
201   auto database_exceeded_callback = [](Evas_Object* view,
202                                        Ewk_Security_Origin* origin,
203                                        const char*,
204                                        uint64_t,
205                                        void*) -> Eina_Bool {
206     std::string protocol(ewk_security_origin_protocol_get(origin));
207     if (protocol == "file://" || protocol == "app://") {
208       // Allow for local origin
209       ewk_view_exceeded_database_quota_reply(view, EINA_TRUE);
210     } else {
211       // Deny for remote origin
212       ewk_view_exceeded_database_quota_reply(view, EINA_FALSE);
213     }
214     return EINA_TRUE;
215   };
216   ewk_view_exceeded_database_quota_callback_set(
217     ewk_view_,
218     database_exceeded_callback,
219     NULL);
220
221   // callback for indexed database quota exceeded
222   auto indexed_db_exceeded_callback = [](Evas_Object* view,
223                                        Ewk_Security_Origin* origin,
224                                        int64_t,
225                                        void*) -> Eina_Bool {
226     std::string protocol(ewk_security_origin_protocol_get(origin));
227     if (protocol == "file://" || protocol == "app://") {
228       // Allow for local origin
229       ewk_view_exceeded_indexed_database_quota_reply(view, EINA_TRUE);
230     } else {
231       // Deny for remote origin
232       ewk_view_exceeded_indexed_database_quota_reply(view, EINA_FALSE);
233     }
234     return EINA_TRUE;
235   };
236   ewk_view_exceeded_indexed_database_quota_callback_set(
237     ewk_view_,
238     indexed_db_exceeded_callback,
239     NULL);
240
241   // callback for localfile quota exceeded
242   auto localfile_exceeded_callback = [](Evas_Object* view,
243                                        Ewk_Security_Origin* origin,
244                                        int64_t,
245                                        void*) -> Eina_Bool {
246     std::string protocol(ewk_security_origin_protocol_get(origin));
247     if (protocol == "file://" || protocol == "app://") {
248       // Allow for local origin
249       ewk_view_exceeded_local_file_system_quota_reply(view, EINA_TRUE);
250     } else {
251       // Deny for remote origin
252       ewk_view_exceeded_local_file_system_quota_reply(view, EINA_FALSE);
253     }
254     return EINA_TRUE;
255   };
256   ewk_view_exceeded_local_file_system_quota_callback_set(
257     ewk_view_,
258     localfile_exceeded_callback,
259     NULL);
260
261   // wrt,message
262   auto wrt_message_callback = [](void* user_data,
263                                  Evas_Object*,
264                                  void* event_info) {
265     WebView* self = static_cast<WebView*>(user_data);
266     Ewk_IPC_Wrt_Message_Data* msg =
267         static_cast<Ewk_IPC_Wrt_Message_Data*>(event_info);
268     if (self->listener_)
269       self->listener_->OnReceivedWrtMessage(self, *msg);
270   };
271   evas_object_smart_callback_add(ewk_view_,
272                                  "wrt,message",
273                                  wrt_message_callback,
274                                  this);
275
276   // rotation support
277   ewk_view_orientation_send(ewk_view_, ToWebRotation(window_->rotation()));
278   rotation_handler_id_ = window_->AddRotationHandler(
279                                   std::bind(&WebView::OnRotation,
280                                   this,
281                                   std::placeholders::_1));
282   // Show webview
283   evas_object_show(ewk_view_);
284 }
285
286 std::string WebView::GetUrl() {
287   return std::string(ewk_view_url_get(ewk_view_));
288 }
289
290 Evas_Object* WebView::evas_object() const {
291   return ewk_view_;
292 }
293
294 void WebView::OnRotation(int degree) {
295   ewk_view_orientation_send(ewk_view_, ToWebRotation(degree));
296 }
297
298 void WebView::OnKeyEvent(Ea_Callback_Type key_type) {
299   std::string keyname;
300   if (key_type == EA_CALLBACK_BACK) {
301     if (EINA_TRUE == ewk_view_text_selection_clear(ewk_view_)) {
302       return;
303     }
304     keyname = kKeyNameBack;
305   } else if (key_type == EA_CALLBACK_MORE) {
306     keyname = kKeyNameMenu;
307   } else {
308     return;
309   }
310
311   if (listener_)
312     listener_->OnHardwareKey(this, keyname);
313 }
314
315
316 }  // namespace wrt
317