WebView Implements
[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       always_run_(false) {
42   Initialize();
43 }
44
45 WebView::~WebView() {
46   window_->RemoveRotationHandler(rotation_handler_id_);
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   // change the visibility
55   ewk_view_visibility_set(ewk_view_, EINA_FALSE);
56
57   if (!always_run_) {
58     // suspend webview
59     ewk_view_suspend(ewk_view_);
60   }
61 }
62
63 void WebView::Resume() {
64   if (!always_run_) {
65     // resume webview
66     ewk_view_resume(ewk_view_);
67   }
68   // change the visiblity
69   ewk_view_visibility_set(ewk_view_, EINA_TRUE);
70 }
71
72 void WebView::Reload() {
73   ewk_view_reload(ewk_view_);
74 }
75
76 void WebView::AlwaysRun(bool run) {
77   always_run_ = run;
78 }
79
80 bool WebView::EvalJavascript(const std::string& script) {
81   return ewk_view_script_execute(ewk_view_, script.c_str(), NULL, NULL);
82 }
83
84 void WebView::Initialize() {
85   ewk_view_ = ewk_view_add_with_context(window_->evas_object(), context_);
86
87   // TODO(sngn.lee): To be implemented - orientation lock
88
89
90   auto key_callback = [](void* user_data,
91                          Evas_Object* /*obj*/,
92                          void* event_info) -> void {
93     WebView* self = static_cast<WebView*>(user_data);
94     Ea_Callback_Type key = static_cast<Ea_Callback_Type>(
95                               reinterpret_cast<int>(event_info));
96     self->OnKeyEvent(key);
97   };
98   ea_object_event_callback_add(ewk_view_,
99                                EA_CALLBACK_BACK,
100                                key_callback,
101                                this);
102   ea_object_event_callback_add(ewk_view_,
103                                EA_CALLBACK_MORE,
104                                key_callback,
105                                this);
106
107
108   // load statred callback
109   auto loadstart_callback = [](void* user_data,
110                                Evas_Object* /*obj*/,
111                                void*) {
112     WebView* self = static_cast<WebView*>(user_data);
113     if (self->listener_)
114       self->listener_->OnLoadStart(self);
115   };
116   evas_object_smart_callback_add(ewk_view_,
117                                  "load,started",
118                                  loadstart_callback,
119                                  this);
120   // load finished callback
121   auto loadfinished_callback = [](void* user_data,
122                                   Evas_Object*,
123                                   void*) {
124     WebView* self = static_cast<WebView*>(user_data);
125     if (self->listener_)
126       self->listener_->OnLoadFinished(self);
127   };
128   evas_object_smart_callback_add(ewk_view_,
129                                  "load,finished",
130                                  loadfinished_callback,
131                                  this);
132
133   // load progress callback
134   auto loadprogress_callback = [](void* user_data,
135                                   Evas_Object*,
136                                   void* event_info) {
137     WebView* self = static_cast<WebView*>(user_data);
138     double* progress = static_cast<double*>(event_info);
139     if (self->listener_)
140       self->listener_->OnLoadProgress(self, *progress);
141   };
142   evas_object_smart_callback_add(ewk_view_,
143                                  "load,progress",
144                                  loadprogress_callback,
145                                  this);
146   // rendered callback
147   auto rendered_callback = [](void* user_data,
148                               Evas_Object*,
149                               void*) {
150     WebView* self = static_cast<WebView*>(user_data);
151     if (self->listener_)
152       self->listener_->OnRendered(self);
153   };
154   evas_object_smart_callback_add(ewk_view_,
155                                  "frame,rendered",
156                                  rendered_callback,
157                                  this);
158
159   // "policy,navigation,decide"
160   auto navigation_decide_callback = [](void* user_data,
161                                        Evas_Object*,
162                                        void* event_info) {
163     WebView* self = static_cast<WebView*>(user_data);
164     Ewk_Policy_Decision* policy =
165             static_cast<Ewk_Policy_Decision*>(event_info);
166     const char* url = ewk_policy_decision_url_get(policy);
167
168     if (self->listener_) {
169       if (self->listener_->OnDidNavigation(self, url))
170         ewk_policy_decision_use(policy);
171       else
172         ewk_policy_decision_ignore(policy);
173     } else {
174       ewk_policy_decision_use(policy);
175     }
176   };
177   evas_object_smart_callback_add(ewk_view_,
178                                  "policy,navigation,decide",
179                                  navigation_decide_callback,
180                                  this);
181
182   // policy,newwindow,decide
183   auto newwindow_decide_callback = [](void* user_data,
184                                       Evas_Object*,
185                                       void* event_info) {
186     WebView* self = static_cast<WebView*>(user_data);
187     Ewk_Policy_Decision* policy =
188             static_cast<Ewk_Policy_Decision*>(event_info);
189
190     const char* url = ewk_policy_decision_url_get(policy);
191
192     if (self->listener_) {
193       if (self->listener_->OnDidNavigation(self, url) &&
194          self->listener_->OnDidOpenWindow(self, url)) {
195          ewk_policy_decision_use(policy);
196       } else {
197         ewk_policy_decision_ignore(policy);
198       }
199     } else {
200       ewk_policy_decision_use(policy);
201     }
202   };
203   evas_object_smart_callback_add(ewk_view_,
204                                  "policy,newwindow,decide",
205                                  newwindow_decide_callback,
206                                  this);
207
208   ewk_view_orientation_send(ewk_view_, ToWebRotation(window_->rotation()));
209   rotation_handler_id_ = window_->AddRotationHandler(
210                                   std::bind(&WebView::OnRotation,
211                                   this,
212                                   std::placeholders::_1));
213   // Show webview
214   evas_object_show(ewk_view_);
215 }
216
217 std::string WebView::GetUrl() {
218   return std::string(ewk_view_url_get(ewk_view_));
219 }
220
221 Evas_Object* WebView::evas_object() const {
222   return ewk_view_;
223 }
224
225 void WebView::OnRotation(int degree) {
226   ewk_view_orientation_send(ewk_view_, ToWebRotation(degree));
227 }
228
229 void WebView::OnKeyEvent(Ea_Callback_Type key_type) {
230   std::string keyname;
231   if (key_type == EA_CALLBACK_BACK) {
232     if (EINA_TRUE == ewk_view_text_selection_clear(ewk_view_)) {
233       return;
234     }
235     keyname = kKeyNameBack;
236   } else if (key_type == EA_CALLBACK_MORE) {
237     keyname = kKeyNameMenu;
238   } else {
239     return;
240   }
241
242   if (listener_)
243     listener_->OnHardwareKey(this, keyname);
244 }
245
246
247 }  // namespace wrt
248