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"
12 #include <EWebKit_internal.h>
13 #include <EWebKit_product.h>
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;
23 Window* Browser::selected_window_ = NULL;
25 Browser::Browser(bool desktop)
26 : toolbox_window_(NULL)
29 , inspector_started_(false)
30 , tracing_enabled_(false) {
32 log_info("UI type: %s", desktop_ ? "desktop" : "mobile");
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());
47 log_info("Runtime Profile : UNKNOWN : ");
50 if (IsEmulatorArch()) {
51 log_info("Runtime Architecture : EMUULATOR : ", IsEmulatorArch());
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();
62 toolbox_window_ = elm_win_util_standard_add(
63 "ubrowser-toolbox", "uBrowser ToolBox");
65 evas_object_resize(toolbox_window_,
66 kToolboxWindowWidth, kToolboxWindowHeight);
67 elm_win_autodel_set(toolbox_window_, EINA_TRUE);
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);
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,
78 evas_object_size_hint_align_set(window_list_, EVAS_HINT_FILL,
80 elm_box_pack_end(box, window_list_);
81 evas_object_show(window_list_);
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);
90 AddButton(bbox, "New Window", "add", NULL, OnNewWindowRequest);
91 AddButton(bbox, "New Incognito Window", "add", NULL,
92 OnNewIncognitoWindowRequest);
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)));
100 evas_object_smart_callback_add(toolbox_window_, "delete,request",
101 &Browser::OnToolboxWindowDelRequest, this);
103 ewk_context_vibration_client_callbacks_set(ctx,
104 &Browser::OnVibrationStart,
105 &Browser::OnVibrationStop,
108 evas_object_show(toolbox_window_);
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);
119 Window& Browser::CreateWindow(bool incognito) {
121 memset(&data, 0, sizeof(data));
124 data.window = new Window(*this, kDefaultDesktopWindowWidth,
125 kDefaultDesktopWindowHeight, incognito);
127 data.window = new Window(*this, kDefaultMobileWindowWidth,
128 kDefaultMobileWindowHeight, incognito);
129 selected_window_ = data.window;
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_,
141 CreateControlButtons(window_list_),
142 &Browser::OnWindowElementClicked,
146 window_map_[data.window->Id()] = data;
149 elm_list_go(window_list_);
151 log_trace("%s: %x", __PRETTY_FUNCTION__, data.window->Id());
156 void Browser::ShowInspectorWindow() {
157 Ewk_Context* ctx = ewk_context_default_get();
158 unsigned int port = ewk_context_inspector_server_start(ctx, 0);
161 snprintf(url, sizeof(url), "http://localhost:%u/", port);
162 Window& win = CreateWindow();
163 win.EnableMouseEvents(true);
164 win.EnableTouchEvents(false);
166 inspector_started_ = true;
169 void Browser::StartInspectorServer() {
170 Ewk_Context* ctx = ewk_context_default_get();
171 unsigned int port = ewk_context_inspector_server_start(ctx, 7777);
173 log_trace("Inspector server started at port: %d\n", port);
176 void Browser::ActivateToolboxWindow() {
177 log_trace("%s", __PRETTY_FUNCTION__);
178 assert(toolbox_window_);
179 elm_win_activate(toolbox_window_);
182 void Browser::StartTracing() {
183 log_trace("%s", __PRETTY_FUNCTION__);
184 ewk_start_tracing("*, disabled-by-default-toplevel.flow", "", "");
185 tracing_enabled_ = true;
188 void Browser::StopTracing() {
189 log_trace("%s", __PRETTY_FUNCTION__);
191 tracing_enabled_ = false;
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;
203 if (haptic_handle_) {
204 device_haptic_stop(haptic_handle_, haptic_effect_);
205 device_haptic_close(haptic_handle_);
206 haptic_handle_ = NULL;
209 if (device_haptic_open(0, &haptic_handle_) != DEVICE_ERROR_NONE) {
210 log_error("__vibration_on_cb:device_haptic_open failed");
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);
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;
230 if (haptic_handle_) {
231 device_haptic_stop(haptic_handle_, haptic_effect_);
232 device_haptic_close(haptic_handle_);
233 haptic_handle_ = NULL;
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;
248 elm_list_go(window_list_);
249 delete window_map_data.window;
250 window_map_.erase(id);
253 void Browser::OnWindowTitleChanged(Window::IdType id, const char* title) {
255 elm_object_item_part_text_set(window_map_[id].list_elm, "default", title);
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);
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);
270 void Browser::AddButton(Evas_Object* parent,
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);
279 elm_object_text_set(bt, label);
281 elm_object_tooltip_text_set(bt, tooltip);
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);
287 evas_object_smart_callback_add(bt, "clicked", cb, this);
288 elm_box_pack_end(parent, bt);
289 evas_object_show(bt);
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);
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;
309 void Browser::OnWindowElementClicked(void* data, Evas_Object*, void*) {
310 selected_window_ = static_cast<Window*>(data);
311 selected_window_->Activate();
314 void Browser::OnWindowClose(void* data, Evas_Object*, void*) {
315 if (selected_window_) {
316 selected_window_->Close();
317 selected_window_ = NULL;
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);
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);
333 void Browser::OnVibrationStart(uint64_t vibration_time, void* data) {
334 Browser* thiz = static_cast<Browser*>(data);
335 thiz->StartVibration(vibration_time);
338 void Browser::OnVibrationStop(void* data) {
339 Browser* thiz = static_cast<Browser*>(data);
340 thiz->StopVibration();
343 Eina_Bool Browser::OnVibrationTimeout(void* data) {
344 Browser::OnVibrationStop(data);
345 return ECORE_CALLBACK_CANCEL;
348 void Browser::Exit() const {
349 #if defined(OS_TIZEN) && defined(TIZEN_APP)