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