3dcda61a2a0ffc34ebd9cf06813a669d277e4c0f
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / ubrowser / browser.cc
1 // Copyright 2014 Samsung Electronics. 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 "browser.h"
6
7 #include "logger.h"
8 #include "tizen/system_info.h"
9
10 #include <assert.h>
11 #include <ewk_context.h>
12 #include <ewk_tracing.h>
13
14 static std::string kHomePage = "http://www.google.com";
15 static int kDefaultMobileWindowWidth = 360;
16 static int kDefaultMobileWindowHeight = 640;
17 static int kDefaultDesktopWindowWidth = 1600;
18 static int kDefaultDesktopWindowHeight = 900;
19 static int kToolboxWindowWidth = 640;
20 static int kToolboxWindowHeight = 400;
21
22 Window* Browser::selected_window_ = NULL;
23
24 Browser::Browser(bool desktop)
25   : toolbox_window_(NULL)
26   , window_list_(NULL)
27   , desktop_(desktop)
28   , inspector_started_(false)
29   , tracing_enabled_(false) {
30
31   log_info("UI type: %s", desktop_ ? "desktop" : "mobile");
32
33   if (IsDesktopProfile()) {
34     log_info("Runtime Profile : DESKTOP : ", IsDesktopProfile());
35   } else if (IsMobileProfile()) {
36     log_info("Runtime Profile : MOBILE : ", IsMobileProfile());
37   } else if (IsTvProfile()) {
38     log_info("Runtime Profile : TV : ", IsTvProfile());
39   } else if (IsWearableProfile()) {
40     log_info("Runtime Profile : WEARABLE : ", IsWearableProfile());
41   } else if (IsIviProfile()) {
42     log_info("Runtime Profile : IVI : ", IsIviProfile());
43   } else if (IsCommonProfile()) {
44     log_info("Runtime Profile : COMMON : ", IsCommonProfile());
45   } else {
46     log_info("Runtime Profile : UNKNOWN : ");
47   }
48
49   if (IsEmulatorArch()) {
50     log_info("Runtime Architecture : EMUULATOR : ", IsEmulatorArch());
51   }
52
53   // If we don't call ewk_context_default_get here, ubrowser crashes in desktop
54   // mode. This is a hack.
55   // FIXME: find a real fix
56   Ewk_Context* ctx = ewk_context_default_get();
57
58   if (desktop_)
59     return;
60
61   toolbox_window_ = elm_win_util_standard_add(
62       "ubrowser-toolbox", "uBrowser ToolBox");
63
64   evas_object_resize(toolbox_window_,
65                      kToolboxWindowWidth, kToolboxWindowHeight);
66   elm_win_autodel_set(toolbox_window_, EINA_TRUE);
67
68   Evas_Object* box = elm_box_add(toolbox_window_);
69   evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
70   elm_win_resize_object_add(toolbox_window_, box);
71   evas_object_show(box);
72
73   window_list_ = elm_list_add(toolbox_window_);
74   elm_list_select_mode_set(window_list_, ELM_OBJECT_SELECT_MODE_ALWAYS);
75   evas_object_size_hint_weight_set(window_list_, EVAS_HINT_EXPAND,
76                                    EVAS_HINT_EXPAND);
77   evas_object_size_hint_align_set(window_list_, EVAS_HINT_FILL,
78                                   EVAS_HINT_FILL);
79   elm_box_pack_end(box, window_list_);
80   evas_object_show(window_list_);
81
82   Evas_Object* bbox = elm_box_add(toolbox_window_);
83   elm_box_horizontal_set(bbox, EINA_TRUE);
84   evas_object_size_hint_weight_set(bbox, EVAS_HINT_EXPAND, 0);
85   evas_object_size_hint_align_set(bbox, EVAS_HINT_FILL, 0);
86   elm_box_pack_end(box, bbox);
87   evas_object_show(bbox);
88
89   AddButton(bbox, "New Window", "add", NULL, OnNewWindowRequest);
90   AddButton(bbox, "New Incognito Window", "add", NULL,
91             OnNewIncognitoWindowRequest);
92
93   if (elm_win_wm_rotation_supported_get(toolbox_window_)) {
94     static const int rots[] = {0, 90, 270};
95     elm_win_wm_rotation_available_rotations_set(
96         toolbox_window_, rots, (sizeof(rots) / sizeof(int)));
97   }
98
99   evas_object_smart_callback_add(toolbox_window_, "delete,request",
100                                  &Browser::OnToolboxWindowDelRequest, this);
101
102   ewk_context_vibration_client_callbacks_set(ctx,
103                                              &Browser::OnVibrationStart,
104                                              &Browser::OnVibrationStop,
105                                              this);
106
107   evas_object_show(toolbox_window_);
108 }
109
110 Browser::~Browser() {
111   while (!window_map_.empty())
112     window_map_.begin()->second.window->Close();
113   Ewk_Context* ctx = ewk_context_default_get();
114   if (inspector_started_)
115     ewk_context_inspector_server_stop(ctx);
116 }
117
118 Window& Browser::CreateWindow(bool incognito) {
119   WindowMapData data;
120   memset(&data, 0, sizeof(data));
121
122   if (desktop_)
123     data.window = new Window(*this, kDefaultDesktopWindowWidth,
124                              kDefaultDesktopWindowHeight, incognito);
125   else
126     data.window = new Window(*this, kDefaultMobileWindowWidth,
127                              kDefaultMobileWindowHeight, incognito);
128   selected_window_ = data.window;
129
130   if (toolbox_window_) {
131     Evas_Object* pb = elm_progressbar_add(toolbox_window_);
132     elm_object_style_set(pb, "wheel");
133     elm_progressbar_pulse_set(pb, EINA_TRUE);
134     evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0);
135     evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
136     data.loading_indicator = pb;
137     data.list_elm = elm_list_item_append(window_list_,
138                                          "New Window",
139                                          pb,
140                                          CreateControlButtons(window_list_),
141                                          &Browser::OnWindowElementClicked,
142                                          data.window);
143   }
144
145   window_map_[data.window->Id()] = data;
146
147   if (window_list_)
148     elm_list_go(window_list_);
149
150   log_trace("%s: %x", __PRETTY_FUNCTION__, data.window->Id());
151
152   return *data.window;
153 }
154
155 void Browser::ShowInspectorWindow() {
156   Ewk_Context* ctx = ewk_context_default_get();
157   unsigned int port = ewk_context_inspector_server_start(ctx, 0);
158   assert(port != 0);
159   char url[1024];
160   snprintf(url, sizeof(url), "http://localhost:%u/", port);
161   Window& win = CreateWindow();
162   win.EnableMouseEvents(true);
163   win.EnableTouchEvents(false);
164   win.LoadURL(url);
165   inspector_started_ = true;
166 }
167
168 void Browser::StartInspectorServer() {
169   Ewk_Context* ctx = ewk_context_default_get();
170   unsigned int port = ewk_context_inspector_server_start(ctx, 7777);
171   assert(port != 0);
172   log_trace("Inspector server started at port: %d\n", port);
173 }
174
175 void Browser::ActivateToolboxWindow() {
176   log_trace("%s", __PRETTY_FUNCTION__);
177   assert(toolbox_window_);
178   elm_win_activate(toolbox_window_);
179 }
180
181 void Browser::StartTracing() {
182   log_trace("%s", __PRETTY_FUNCTION__);
183   ewk_start_tracing("*, disabled-by-default-toplevel.flow", "", "");
184   tracing_enabled_ = true;
185 }
186
187 void Browser::StopTracing() {
188   log_trace("%s", __PRETTY_FUNCTION__);
189   ewk_stop_tracing();
190   tracing_enabled_ = false;
191 }
192
193 void Browser::StartVibration(uint64_t duration) {
194   log_trace("%s: %d", __PRETTY_FUNCTION__, duration);
195 #if defined(OS_TIZEN)
196   if (IsMobileProfile() || IsWearableProfile()) {
197     if (haptic_timer_id_) {
198       ecore_timer_del(haptic_timer_id_);
199       haptic_timer_id_ = NULL;
200     }
201
202     if (haptic_handle_) {
203       device_haptic_stop(haptic_handle_, haptic_effect_);
204       device_haptic_close(haptic_handle_);
205       haptic_handle_ = NULL;
206     }
207
208     if (device_haptic_open(0, &haptic_handle_) != DEVICE_ERROR_NONE) {
209       log_error("__vibration_on_cb:device_haptic_open failed");
210       return;
211     }
212
213     device_haptic_vibrate(haptic_handle_, duration, 100, &haptic_effect_);
214     double in = (double)((double)(duration) / (double)(1000));
215     haptic_timer_id_ = ecore_timer_add(in, &Browser::OnVibrationTimeout, this);
216   }
217 #endif
218 }
219
220 void Browser::StopVibration() {
221   log_trace("%s", __PRETTY_FUNCTION__);
222 #if defined(OS_TIZEN)
223   if (IsMobileProfile() || IsWearableProfile()) {
224     if (haptic_timer_id_) {
225       ecore_timer_del(haptic_timer_id_);
226       haptic_timer_id_ = NULL;
227     }
228
229     if (haptic_handle_) {
230       device_haptic_stop(haptic_handle_, haptic_effect_);
231       device_haptic_close(haptic_handle_);
232       haptic_handle_ = NULL;
233     }
234   }
235 #endif
236 }
237
238 void Browser::OnWindowDestroyed(Window::IdType id) {
239   log_trace("%s: %x", __PRETTY_FUNCTION__, id);
240   assert(window_map_.find(id) != window_map_.end());
241   WindowMapData window_map_data = window_map_[id];
242   if (window_map_data.list_elm)
243     elm_object_item_del(window_map_data.list_elm);
244   if (window_map_data.window == selected_window_)
245     selected_window_ = NULL;
246   if (window_list_)
247     elm_list_go(window_list_);
248   delete window_map_data.window;
249   window_map_.erase(id);
250 }
251
252 void Browser::OnWindowTitleChanged(Window::IdType id, const char* title) {
253   if (toolbox_window_)
254     elm_object_item_part_text_set(window_map_[id].list_elm, "default", title);
255 }
256
257 void Browser::OnWindowLoadStarted(Window::IdType id) {
258   assert(window_map_.find(id) != window_map_.end());
259   if (window_map_[id].loading_indicator)
260     elm_progressbar_pulse(window_map_[id].loading_indicator, EINA_TRUE);
261 }
262
263 void Browser::OnWindowLoadFinished(Window::IdType id) {
264   assert(window_map_.find(id) != window_map_.end());
265   if (window_map_[id].loading_indicator)
266     elm_progressbar_pulse(window_map_[id].loading_indicator, EINA_FALSE);
267 }
268
269 void Browser::AddButton(Evas_Object* parent,
270                         const char* label,
271                         const char* icon,
272                         const char* tooltip,
273                         Evas_Smart_Cb cb) {
274   Evas_Object* bt = elm_button_add(parent);
275   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
276   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, 0.5);
277   if (label)
278     elm_object_text_set(bt, label);
279   if (tooltip)
280     elm_object_tooltip_text_set(bt, tooltip);
281   if (icon) {
282     Evas_Object* icon_elm = elm_icon_add(bt);
283     elm_icon_standard_set(icon_elm, icon);
284     elm_object_part_content_set(bt, "icon", icon_elm);
285   }
286   evas_object_smart_callback_add(bt, "clicked", cb, this);
287   elm_box_pack_end(parent, bt);
288   evas_object_show(bt);
289 }
290
291 Evas_Object* Browser::CreateControlButtons(Evas_Object* parent) {
292   Evas_Object* box = elm_box_add(parent);
293   elm_box_horizontal_set(box, EINA_TRUE);
294   evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
295   evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
296   AddButton(box, NULL, "close", "Close", &Browser::OnWindowClose);
297   evas_object_show(box);
298   return box;
299 }
300
301 void Browser::OnToolboxWindowDelRequest(void* data, Evas_Object*, void*) {
302   Browser* thiz = static_cast<Browser*>(data);
303   while (!thiz->window_map_.empty())
304     thiz->window_map_.begin()->second.window->Close();
305   thiz->toolbox_window_ = NULL;
306 }
307
308 void Browser::OnWindowElementClicked(void* data, Evas_Object*, void*) {
309   selected_window_ = static_cast<Window*>(data);
310   selected_window_->Activate();
311 }
312
313 void Browser::OnWindowClose(void* data, Evas_Object*, void*) {
314   if (selected_window_) {
315     selected_window_->Close();
316     selected_window_ = NULL;
317   }
318 }
319
320 void Browser::OnNewWindowRequest(void* data, Evas_Object*, void*) {
321   Browser* thiz = static_cast<Browser*>(data);
322   Window& win = thiz->CreateWindow();
323   win.LoadURL(kHomePage);
324 }
325
326 void Browser::OnNewIncognitoWindowRequest(void* data, Evas_Object*, void*) {
327   Browser* thiz = static_cast<Browser*>(data);
328   Window& win = thiz->CreateWindow(true);
329   win.LoadURL(kHomePage);
330 }
331
332 void Browser::OnVibrationStart(uint64_t vibration_time, void* data) {
333   Browser* thiz = static_cast<Browser*>(data);
334   thiz->StartVibration(vibration_time);
335 }
336
337 void Browser::OnVibrationStop(void* data) {
338   Browser* thiz = static_cast<Browser*>(data);
339   thiz->StopVibration();
340 }
341
342 Eina_Bool Browser::OnVibrationTimeout(void* data) {
343   Browser::OnVibrationStop(data);
344   return ECORE_CALLBACK_CANCEL;
345 }
346
347 void Browser::Exit() const {
348 #if defined(OS_TIZEN) && defined(TIZEN_APP)
349   ui_app_exit();
350 #else
351   elm_exit();
352 #endif
353 }