Implements extension loader and server
[platform/framework/web/crosswalk-tizen.git] / src / runtime / web_application.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_application.h"
6
7 #include <cert-service.h>
8 #include <app.h>
9 #include <ewk_chromium.h>
10 #include <algorithm>
11 #include <memory>
12
13 #include "common/message_types.h"
14 #include "runtime/native_window.h"
15 #include "runtime/command_line.h"
16 #include "runtime/web_view.h"
17 #include "runtime/vibration_manager.h"
18
19 namespace {
20   // TODO(sngn.lee) : It should be declare in common header
21   const char* kKeyNameBack = "back";
22
23   const char* kAppControlEventScript = \
24         "var __event = document.createEvent(\"CustomEvent\");\n"
25         "__event.initCustomEvent(\"appcontrol\", true, true);\n"
26         "document.dispatchEvent(__event);\n"
27         "\n"
28         "for (var i=0; i < window.frames.length; i++)\n"
29         "{ window.frames[i].document.dispatchEvent(__event); }";
30   const char* kBackKeyEventScript = \
31         "var __event = document.createEvent(\"CustomEvent\");\n"
32         "__event.initCustomEvent(\"tizenhwkey\", true, true);\n"
33         "__event.keyName = \"back\";\n"
34         "document.dispatchEvent(__event);\n"
35         "\n"
36         "for (var i=0; i < window.frames.length; i++)\n"
37         "{ window.frames[i].document.dispatchEvent(__event); }";
38 }  // namespace
39
40 namespace wrt {
41
42 WebApplication::WebApplication(const std::string& appid)
43     : initialized_(false),
44       appid_(appid),
45       ewk_context_(ewk_context_new()) {
46   // app_data_path
47   std::unique_ptr<char, decltype(std::free)*>
48     path {app_get_data_path(), std::free};
49   app_data_path_ = path.get();
50
51   // extension_server
52   extension_server_ = new ExtensionServer(ewk_context_);
53 }
54
55 WebApplication::~WebApplication() {
56   ewk_context_delete(ewk_context_);
57   if (extension_server_)
58     delete extension_server_;
59 }
60
61 bool WebApplication::Initialize(NativeWindow* window) {
62   window_ = window;
63
64   // start extension server
65   if (extension_server_)
66     extension_server_->Start();
67
68   // ewk setting
69   ewk_context_cache_model_set(ewk_context_, EWK_CACHE_MODEL_DOCUMENT_BROWSER);
70
71   // cookie
72   auto cookie_manager = ewk_context_cookie_manager_get(ewk_context_);
73   ewk_cookie_manager_accept_policy_set(cookie_manager,
74                                        EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
75
76   // set persistent storage path
77   std::string cookie_path = data_path() + ".cookie";
78   ewk_cookie_manager_persistent_storage_set(
79                                       cookie_manager, cookie_path.c_str(),
80                                       EWK_COOKIE_PERSISTENT_STORAGE_SQLITE);
81
82   // vibration callback
83   auto vibration_start_callback = [](uint64_t ms, void*) {
84     platform::VibrationManager::GetInstance()->Start(static_cast<int>(ms));
85   };
86   auto vibration_stop_callback = [](void* /*user_data*/) {
87     platform::VibrationManager::GetInstance()->Stop();
88   };
89   ewk_context_vibration_client_callbacks_set(ewk_context_,
90                                              vibration_start_callback,
91                                              vibration_stop_callback,
92                                              NULL);
93
94   // Set certificate path
95   char* cert_path = cert_svc_get_certificate_crt_file_path();
96   if (cert_path != NULL) {
97     ewk_context_certificate_file_set(ewk_context_, cert_path);
98   }
99
100   // TODO(sngn.lee): find the proxy url
101   // ewk_context_proxy_uri_set(ewk_context_, ... );
102   return true;
103 }
104
105 void WebApplication::Launch() {
106   initialized_ = true;
107   WebView* view = new WebView(window_, ewk_context_);
108
109   // TODO(sngn.lee): Get the start file
110   view->LoadUrl("index.html");
111   view_stack_.push_front(view);
112   window_->SetContent(view->evas_object());
113
114   // TODO(sngn.lee): below code only debug code
115   auto callback = [](void* data, Evas* e, Evas_Object* obj, void* eventInfo) -> void {
116     int x,y,w,h;
117     evas_object_geometry_get(obj, &x,&y,&w,&h);
118     fprintf(stderr,"resize ! (%d, %d, %d, %d)\n", x,y,w,h);
119   };
120   evas_object_event_callback_add(view->evas_object(), EVAS_CALLBACK_RESIZE, callback, NULL );
121
122   // TODO(sngn.lee): check the below code location.
123   // in Wearable, webkit can render contents before show window
124   // but Mobile, webkit can't render contents before show window
125   window_->Show();
126 }
127
128 void WebApplication::AppControl() {
129   // TODO(sngn.lee): find the app control url and the reset options
130
131   // TODO(sngn.lee): Set the injected bundle into extension process
132
133
134   if (true) {
135     // Reset to context
136     ClearViewStack();
137     WebView* view = new WebView(window_, ewk_context_);
138     view->LoadUrl("file:///index.html");
139     view_stack_.push_front(view);
140     window_->SetContent(view->evas_object());
141   } else {
142     // Send Event
143     SendAppControlEvent();
144   }
145 }
146
147 void WebApplication::SendAppControlEvent() {
148   auto it = view_stack_.begin();
149   while (it != view_stack_.end()) {
150     (*it)->EvalJavascript(kAppControlEventScript);
151   }
152 }
153
154 void WebApplication::ClearViewStack() {
155   window_->SetContent(NULL);
156   auto it = view_stack_.begin();
157   while (it != view_stack_.end()) {
158     (*it)->Suspend();
159     delete *it;
160   }
161   view_stack_.clear();
162 }
163
164 void WebApplication::Resume() {
165   if (view_stack_.size() > 0 && view_stack_.front() != NULL)
166     view_stack_.front()->SetVisibility(true);
167
168   // TODO(sngn.lee) : should be check the background support option
169   // if background suuport options was on, skip below code
170
171   auto it = view_stack_.begin();
172   for ( ; it != view_stack_.end(); ++it) {
173     (*it)->Resume();
174   }
175 }
176
177 void WebApplication::Suspend() {
178   if (view_stack_.size() > 0 && view_stack_.front() != NULL)
179     view_stack_.front()->SetVisibility(false);
180
181   // TODO(sngn.lee) : should be check the background support option
182   // if background suuport options was on, skip below code
183   auto it = view_stack_.begin();
184   for ( ; it != view_stack_.end(); ++it) {
185     (*it)->Suspend();
186   }
187 }
188
189 void WebApplication::OnCreatedNewWebView(WebView* view, WebView* new_view) {
190   if (view_stack_.size() > 0 && view_stack_.front() != NULL)
191     view_stack_.front()->SetVisibility(false);
192
193   view_stack_.push_front(new_view);
194   window_->SetContent(new_view->evas_object());
195 }
196
197 void WebApplication::OnClosedWebView(WebView * view) {
198   if (view_stack_.size() == 0)
199     return;
200
201   WebView* current = view_stack_.front();
202   if (current == view) {
203     view_stack_.pop_front();
204   } else {
205     auto found = std::find(view_stack_.begin(), view_stack_.end(), view);
206     if (found != view_stack_.end()) {
207       view_stack_.erase(found);
208     }
209   }
210
211   if (view_stack_.size() == 0) {
212     // TODO(sngn.lee): terminate the webapp
213   } else if (current != view_stack_.front()) {
214     view_stack_.front()->SetVisibility(true);
215     window_->SetContent(view_stack_.front()->evas_object());
216   }
217
218   delete view;
219 }
220
221 void WebApplication::OnRendered(WebView* view) {
222 }
223
224
225 void WebApplication::OnReceivedWrtMessage(
226     WebView* /*view*/,
227     Ewk_IPC_Wrt_Message_Data* message) {
228
229   Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(message);
230
231   #define START_WITHS(x, s) (strncmp(x, s, strlen(s)) == 0)
232
233   if (START_WITHS(msg_type, message_types::kExtensionTypePrefix)) {
234     extension_server_->HandleWrtMessage(message);
235   }
236
237   // TODO(wy80.choi): handle other message type?
238   // changeUserAgent, clearAllCookie, GetWindowID, hide, exit, blockedUrl
239
240
241   #undef START_WITHS
242 }
243
244 void WebApplication::OnOrientationLock(WebView* view,
245                                        bool lock,
246                                        int preferred_rotation) {
247   if (view_stack_.size() == 0)
248     return;
249
250   // Only top-most view can set the orientation relate operation
251   if (view_stack_.front() != view)
252     return;
253
254   // TODO(sngn.lee): check the orientaion setting
255   // if allow the auto orientation
256   // if (is not allow orientation) {
257   //   return;
258   // }
259   if ( lock ) {
260     window_->SetRotationLock(preferred_rotation);
261   } else {
262     window_->SetAutoRotation();
263   }
264 }
265
266 void WebApplication::OnHardwareKey(WebView* view, const std::string& keyname) {
267   // TODO(sngn.lee): Check the hw key event was enabled
268   if (true && kKeyNameBack == keyname) {
269     view->EvalJavascript(kBackKeyEventScript);
270   }
271 }
272
273 }  // namespace wrt