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