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.
8 #include "tizen/system_info.h"
11 #include <ewk_context.h>
12 #include <ewk_tracing.h>
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;
22 Window* Browser::selected_window_ = NULL;
24 Browser::Browser(bool desktop)
25 : toolbox_window_(NULL)
28 , inspector_started_(false)
29 , tracing_enabled_(false) {
31 log_info("UI type: %s", desktop_ ? "desktop" : "mobile");
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());
46 log_info("Runtime Profile : UNKNOWN : ");
49 if (IsEmulatorArch()) {
50 log_info("Runtime Architecture : EMUULATOR : ", IsEmulatorArch());
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();
61 toolbox_window_ = elm_win_util_standard_add(
62 "ubrowser-toolbox", "uBrowser ToolBox");
64 evas_object_resize(toolbox_window_,
65 kToolboxWindowWidth, kToolboxWindowHeight);
66 elm_win_autodel_set(toolbox_window_, EINA_TRUE);
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);
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,
77 evas_object_size_hint_align_set(window_list_, EVAS_HINT_FILL,
79 elm_box_pack_end(box, window_list_);
80 evas_object_show(window_list_);
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);
89 AddButton(bbox, "New Window", "add", NULL, OnNewWindowRequest);
90 AddButton(bbox, "New Incognito Window", "add", NULL,
91 OnNewIncognitoWindowRequest);
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)));
99 evas_object_smart_callback_add(toolbox_window_, "delete,request",
100 &Browser::OnToolboxWindowDelRequest, this);
102 ewk_context_vibration_client_callbacks_set(ctx,
103 &Browser::OnVibrationStart,
104 &Browser::OnVibrationStop,
107 evas_object_show(toolbox_window_);
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);
118 Window& Browser::CreateWindow(bool incognito) {
120 memset(&data, 0, sizeof(data));
123 data.window = new Window(*this, kDefaultDesktopWindowWidth,
124 kDefaultDesktopWindowHeight, incognito);
126 data.window = new Window(*this, kDefaultMobileWindowWidth,
127 kDefaultMobileWindowHeight, incognito);
128 selected_window_ = data.window;
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_,
140 CreateControlButtons(window_list_),
141 &Browser::OnWindowElementClicked,
145 window_map_[data.window->Id()] = data;
148 elm_list_go(window_list_);
150 log_trace("%s: %x", __PRETTY_FUNCTION__, data.window->Id());
155 void Browser::ShowInspectorWindow() {
156 Ewk_Context* ctx = ewk_context_default_get();
157 unsigned int port = ewk_context_inspector_server_start(ctx, 0);
160 snprintf(url, sizeof(url), "http://localhost:%u/", port);
161 Window& win = CreateWindow();
162 win.EnableMouseEvents(true);
163 win.EnableTouchEvents(false);
165 inspector_started_ = true;
168 void Browser::StartInspectorServer() {
169 Ewk_Context* ctx = ewk_context_default_get();
170 unsigned int port = ewk_context_inspector_server_start(ctx, 7777);
172 log_trace("Inspector server started at port: %d\n", port);
175 void Browser::ActivateToolboxWindow() {
176 log_trace("%s", __PRETTY_FUNCTION__);
177 assert(toolbox_window_);
178 elm_win_activate(toolbox_window_);
181 void Browser::StartTracing() {
182 log_trace("%s", __PRETTY_FUNCTION__);
183 ewk_start_tracing("*, disabled-by-default-toplevel.flow", "", "");
184 tracing_enabled_ = true;
187 void Browser::StopTracing() {
188 log_trace("%s", __PRETTY_FUNCTION__);
190 tracing_enabled_ = false;
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;
202 if (haptic_handle_) {
203 device_haptic_stop(haptic_handle_, haptic_effect_);
204 device_haptic_close(haptic_handle_);
205 haptic_handle_ = NULL;
208 if (device_haptic_open(0, &haptic_handle_) != DEVICE_ERROR_NONE) {
209 log_error("__vibration_on_cb:device_haptic_open failed");
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);
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;
229 if (haptic_handle_) {
230 device_haptic_stop(haptic_handle_, haptic_effect_);
231 device_haptic_close(haptic_handle_);
232 haptic_handle_ = NULL;
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;
247 elm_list_go(window_list_);
248 delete window_map_data.window;
249 window_map_.erase(id);
252 void Browser::OnWindowTitleChanged(Window::IdType id, const char* title) {
254 elm_object_item_part_text_set(window_map_[id].list_elm, "default", title);
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);
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);
269 void Browser::AddButton(Evas_Object* parent,
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);
278 elm_object_text_set(bt, label);
280 elm_object_tooltip_text_set(bt, tooltip);
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);
286 evas_object_smart_callback_add(bt, "clicked", cb, this);
287 elm_box_pack_end(parent, bt);
288 evas_object_show(bt);
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);
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;
308 void Browser::OnWindowElementClicked(void* data, Evas_Object*, void*) {
309 selected_window_ = static_cast<Window*>(data);
310 selected_window_->Activate();
313 void Browser::OnWindowClose(void* data, Evas_Object*, void*) {
314 if (selected_window_) {
315 selected_window_->Close();
316 selected_window_ = NULL;
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);
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);
332 void Browser::OnVibrationStart(uint64_t vibration_time, void* data) {
333 Browser* thiz = static_cast<Browser*>(data);
334 thiz->StartVibration(vibration_time);
337 void Browser::OnVibrationStop(void* data) {
338 Browser* thiz = static_cast<Browser*>(data);
339 thiz->StopVibration();
342 Eina_Bool Browser::OnVibrationTimeout(void* data) {
343 Browser::OnVibrationStop(data);
344 return ECORE_CALLBACK_CANCEL;
347 void Browser::Exit() const {
348 #if defined(OS_TIZEN) && defined(TIZEN_APP)