From f81d96004d9c227ae7ee2fb5c32d31a6f8671b26 Mon Sep 17 00:00:00 2001 From: Piotr Tworek Date: Mon, 8 Dec 2014 15:34:07 +0100 Subject: [PATCH] uBrowser: Reference EWK browser application This is basically my attempt at implementing more usable test application for for chromium-ewk. Currently efl_webview_app is rather limited and it's codebase is messy. It's main adventage is it works on both Tizen and desktop. Mini browser has a few more features but it only runs on tizen. Personally, I consider it's code to be of similar quality as efl_webview_app. uBrowser on the other hand works on both tizen and desktop, has simiar feature set on both platforms and tries to split the code into smaller chunks that are hopefully easier to understand and maintain. Compared to mini_browser it's currently missing 2 features: 1. It does not support vibration. (I could not get it work on mini_browser, but the code is there) 2. It does not have any find in page funcionality. (Mini browser has one button that allows users search for hardcoded word 'google') What is more important however, uBrowser does support multi window mode. It's possible to open/close/switch between windows. I consider this feature important because I've started the whole project when I had to debug some multi-window related problems and none of the existing apps made it easy. After that I just kept adding new features whenever I needed them and they were either not available or did not work well enough in other apps. The app is far from finished and it probably has a few bugs. Still, I decided there is no point in keeping it for myself any longer. It's nicely separated from other EWK components and does not take a long time to build. Hopefully other people will add even more features to it. At some point it may even replace old reference EWK apps. Reviewed by: Antonio Gomes, Kamil Klimek, arno renevier Change-Id: I5f9cbdc9cb9e6bd801d3d02feff1ad02e97569b5 Signed-off-by: Piotr Tworek --- tizen_src/build/common.sh | 2 +- tizen_src/ewk/chromium-ewk.gyp | 3 +- tizen_src/ewk/ubrowser/browser.cc | 209 +++++++++++++++++++ tizen_src/ewk/ubrowser/browser.h | 58 ++++++ tizen_src/ewk/ubrowser/logger.cc | 141 +++++++++++++ tizen_src/ewk/ubrowser/logger.h | 72 +++++++ tizen_src/ewk/ubrowser/main.cc | 163 +++++++++++++++ tizen_src/ewk/ubrowser/ubrowser.gypi | 48 +++++ tizen_src/ewk/ubrowser/ubrowser.png | Bin 0 -> 4234 bytes tizen_src/ewk/ubrowser/ubrowser.sh | 26 +++ tizen_src/ewk/ubrowser/ubrowser.xml | 11 + tizen_src/ewk/ubrowser/window.cc | 311 ++++++++++++++++++++++++++++ tizen_src/ewk/ubrowser/window.h | 65 ++++++ tizen_src/ewk/ubrowser/window_ui.cc | 331 ++++++++++++++++++++++++++++++ tizen_src/ewk/ubrowser/window_ui.h | 69 +++++++ tizen_src/packaging/chromium-efl.manifest | 1 + tizen_src/packaging/chromium-efl.spec | 4 +- 17 files changed, 1511 insertions(+), 3 deletions(-) create mode 100644 tizen_src/ewk/ubrowser/browser.cc create mode 100644 tizen_src/ewk/ubrowser/browser.h create mode 100644 tizen_src/ewk/ubrowser/logger.cc create mode 100644 tizen_src/ewk/ubrowser/logger.h create mode 100644 tizen_src/ewk/ubrowser/main.cc create mode 100644 tizen_src/ewk/ubrowser/ubrowser.gypi create mode 100644 tizen_src/ewk/ubrowser/ubrowser.png create mode 100755 tizen_src/ewk/ubrowser/ubrowser.sh create mode 100644 tizen_src/ewk/ubrowser/ubrowser.xml create mode 100644 tizen_src/ewk/ubrowser/window.cc create mode 100644 tizen_src/ewk/ubrowser/window.h create mode 100644 tizen_src/ewk/ubrowser/window_ui.cc create mode 100644 tizen_src/ewk/ubrowser/window_ui.h diff --git a/tizen_src/build/common.sh b/tizen_src/build/common.sh index e0fa945..d2b9e4b 100644 --- a/tizen_src/build/common.sh +++ b/tizen_src/build/common.sh @@ -137,7 +137,7 @@ function hostGypChromiumEfl() { function hostNinja() { if [[ $SKIP_NINJA == 0 ]]; then - TARGETS="chromium-efl efl_webprocess chromium-ewk efl_webview_app" + TARGETS="chromium-efl efl_webprocess chromium-ewk efl_webview_app ubrowser" if [[ $BUILD_EWK_UNITTESTS == 1 ]]; then TARGETS="$TARGETS ewk_unittests" fi diff --git a/tizen_src/ewk/chromium-ewk.gyp b/tizen_src/ewk/chromium-ewk.gyp index 5c4669d..dda6c8e 100644 --- a/tizen_src/ewk/chromium-ewk.gyp +++ b/tizen_src/ewk/chromium-ewk.gyp @@ -26,7 +26,8 @@ ]}, 'includes': [ - 'unittest/ewk-tests.gypi' + 'unittest/ewk-tests.gypi', + 'ubrowser/ubrowser.gypi', ], 'targets': [{ diff --git a/tizen_src/ewk/ubrowser/browser.cc b/tizen_src/ewk/ubrowser/browser.cc new file mode 100644 index 0000000..84c5da7 --- /dev/null +++ b/tizen_src/ewk/ubrowser/browser.cc @@ -0,0 +1,209 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "browser.h" + +#include +#include + +#include "logger.h" + +static std::string kHomePage = "http://www.google.com"; +static int kDefaultMobileWindowWidth = 360; +static int kDefaultMobileWindowHeight = 640; +static int kDefaultDesktopWindowWidth = 1600; +static int kDefaultDesktopWindowHeight = 900; +static int kToolboxWindowWidth = 640; +static int kToolboxWindowHeight = 400; + +Window* Browser::selected_window_; + +Browser::Browser(bool desktop) + : toolbox_window_(NULL) + , window_list_(NULL) + , desktop_(desktop) + , inspector_started_(false) { + + log_info("UI type: %s", desktop_ ? "desktop" : "mobile"); + if (desktop_) + return; + + toolbox_window_ = elm_win_util_standard_add( + "ubrowser-toolbox", "uBrowser ToolBox"); + + evas_object_resize(toolbox_window_, + kToolboxWindowWidth, kToolboxWindowHeight); + elm_win_autodel_set(toolbox_window_, EINA_TRUE); + + Evas_Object* box = elm_box_add(toolbox_window_); + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(toolbox_window_, box); + evas_object_show(box); + + window_list_ = elm_list_add(toolbox_window_); + evas_object_size_hint_weight_set(window_list_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(window_list_, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, window_list_); + evas_object_show(window_list_); + + Evas_Object* bbox = elm_box_add(toolbox_window_); + elm_box_horizontal_set(bbox, EINA_TRUE); + evas_object_size_hint_weight_set(bbox, EVAS_HINT_EXPAND, 0); + evas_object_size_hint_align_set(bbox, EVAS_HINT_FILL, 0); + elm_box_pack_end(box, bbox); + evas_object_show(bbox); + + AddButton(bbox, "New Window", "add", NULL, OnNewWindowRequest); + + if (elm_win_wm_rotation_supported_get(toolbox_window_)) { + static const int rots[] = {0, 90, 270}; + elm_win_wm_rotation_available_rotations_set( + toolbox_window_, rots, (sizeof(rots) / sizeof(int))); + } + + evas_object_smart_callback_add(toolbox_window_, "delete,request", + &Browser::OnToolboxWindowDelRequest, this); + + evas_object_show(toolbox_window_); +} + +Browser::~Browser() { + assert(window_map_.empty()); + Ewk_Context* ctx = ewk_context_default_get(); + if (inspector_started_) + ewk_context_inspector_server_stop(ctx); +} + +Window& Browser::CreateWindow() { + WindowMapData data; + memset(&data, 0, sizeof(data)); + + if (desktop_) + data.window = new Window(*this, kDefaultDesktopWindowWidth, + kDefaultDesktopWindowHeight); + else + data.window = new Window(*this, kDefaultMobileWindowWidth, + kDefaultMobileWindowHeight); + + if (toolbox_window_) { + Evas_Object* pb = elm_progressbar_add(toolbox_window_); + elm_object_style_set(pb, "wheel"); + elm_progressbar_pulse_set(pb, EINA_TRUE); + evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0); + evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + data.loading_indicator = pb; + data.list_elm = elm_list_item_append(window_list_, + "New Window", pb, CreateControlButtons(window_list_), + &Browser::OnWindowElementClicked, data.window); + } + + window_map_[data.window->Id()] = data; + + if (window_list_) + elm_list_go(window_list_); + + log_trace("%s: %x", __PRETTY_FUNCTION__, data.window->Id()); + + return *data.window; +} + +void Browser::ShowInspectorWindow() { + Ewk_Context* ctx = ewk_context_default_get(); + unsigned int port = ewk_context_inspector_server_start(ctx, 0); + assert(port != 0); + char url[1024]; + snprintf(url, sizeof(url), "http://localhost:%u/", port); + Window& win = CreateWindow(); + win.EnableMouseEvents(true); + win.EnableTouchEvents(false); + win.LoadURL(url); + inspector_started_ = true; +} + +void Browser::ActivateToolboxWindow() { + log_trace("%s", __PRETTY_FUNCTION__); + assert(toolbox_window_); + elm_win_activate(toolbox_window_); +} + +void Browser::OnWindowDestroyed(Window::IdType id) { + log_trace("%s: %x", __PRETTY_FUNCTION__, id); + assert(window_map_.find(id) != window_map_.end()); + if (window_map_[id].list_elm) + elm_object_item_del(window_map_[id].list_elm); + if (window_map_[id].window == selected_window_) + selected_window_ = NULL; + if (window_list_) + elm_list_go(window_list_); + window_map_.erase(id); +} + +void Browser::OnWindowTitleChanged(Window::IdType id, const char* title) { + if (toolbox_window_) + elm_object_item_part_text_set(window_map_[id].list_elm, "default", title); +} + +void Browser::OnWindowLoadStarted(Window::IdType id) { + assert(window_map_.find(id) != window_map_.end()); + elm_progressbar_pulse(window_map_[id].loading_indicator, EINA_TRUE); +} + +void Browser::OnWindowLoadFinished(Window::IdType id) { + assert(window_map_.find(id) != window_map_.end()); + elm_progressbar_pulse(window_map_[id].loading_indicator, EINA_FALSE); +} + +void Browser::AddButton(Evas_Object* parent, const char* label, + const char* icon, const char* tooltip, Evas_Smart_Cb cb) { + Evas_Object *bt = elm_button_add(parent); + evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, 0.5); + if (label) + elm_object_text_set(bt, label); + if (tooltip) + elm_object_tooltip_text_set(bt, tooltip); + if (icon) { + Evas_Object* icon_elm = elm_icon_add(bt); + elm_icon_standard_set(icon_elm, icon); + elm_object_part_content_set(bt, "icon", icon_elm); + } + evas_object_smart_callback_add(bt, "clicked", cb, this); + elm_box_pack_end(parent, bt); + evas_object_show(bt); +} + +Evas_Object* Browser::CreateControlButtons(Evas_Object* parent) { + Evas_Object* box = elm_box_add(parent); + elm_box_horizontal_set(box, EINA_TRUE); + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); + AddButton(box, NULL, "close", "Close", &Browser::OnWindowClose); + evas_object_show(box); + return box; +} + +void Browser::OnToolboxWindowDelRequest(void* data, Evas_Object*, void*) { + Browser* thiz = static_cast(data); + WindowMap::iterator it = thiz->window_map_.begin(); + while (!thiz->window_map_.empty()) + thiz->window_map_.begin()->second.window->Close(); + thiz->toolbox_window_ = NULL; +} + +void Browser::OnWindowElementClicked(void *data, Evas_Object*, void*) { + selected_window_ = static_cast(data); + selected_window_->Activate(); +} + +void Browser::OnWindowClose(void *data, Evas_Object*, void*) { + assert(selected_window_); + selected_window_->Close(); + selected_window_ = NULL; +} + +void Browser::OnNewWindowRequest(void *data, Evas_Object*, void*) { + Browser *thiz = static_cast(data); + Window& win = thiz->CreateWindow(); + win.LoadURL(kHomePage); +} diff --git a/tizen_src/ewk/ubrowser/browser.h b/tizen_src/ewk/ubrowser/browser.h new file mode 100644 index 0000000..925bf0d --- /dev/null +++ b/tizen_src/ewk/ubrowser/browser.h @@ -0,0 +1,58 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef _BROWSER_H_ +#define _BROWSER_H_ + +#include +#include +#include + +#include "window.h" + +class Browser { + public: + Browser(bool desktop); + ~Browser(); + + Window& CreateWindow(); + void ShowInspectorWindow(); + void ActivateToolboxWindow(); + bool IsDesktop() const { return desktop_; } + + void OnWindowDestroyed(Window::IdType id); + void OnWindowURLChanged(Window::IdType id, const char*); + void OnWindowTitleChanged(Window::IdType id, const char*); + void OnWindowLoadStarted(Window::IdType id); + void OnWindowLoadFinished(Window::IdType id); + + private: + void AddButton(Evas_Object*, const char*, const char*, + const char*, Evas_Smart_Cb); + Evas_Object* CreateControlButtons(Evas_Object*); + + static void OnToolboxWindowDelRequest(void*, Evas_Object*, void*); + static void OnWindowElementClicked(void *data, Evas_Object*, void*); + static void OnWindowClose(void *data, Evas_Object*, void*); + static void OnNewWindowRequest(void *data, Evas_Object*, void*); + + typedef struct _WindowMapData { + Window* window; + Elm_Object_Item* list_elm; + Evas_Object* loading_indicator; + } WindowMapData; + + typedef std::map WindowMap; + + WindowMap window_map_; + static Window* selected_window_; + + Evas_Object* toolbox_window_; + Evas_Object* window_list_; + + bool desktop_; + bool inspector_started_; +}; + +#endif // _BROWSER_H_ diff --git a/tizen_src/ewk/ubrowser/logger.cc b/tizen_src/ewk/ubrowser/logger.cc new file mode 100644 index 0000000..fa128da --- /dev/null +++ b/tizen_src/ewk/ubrowser/logger.cc @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 2013 Peter Tworek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "logger.h" + +#include +#include +#include + +/* Format headers used by logger */ +#define INFO_FORMAT "\e[1;32m[INFO]\e[00m %s" +#define INFO_FORMAT_NC "[INFO] %s" +#define WARN_FORMAT "\e[1;33m[WARN]\e[00m %s" +#define WARN_FORMAT_NC "[WARN] %s" +#define ERROR_FORMAT "\e[1;31m[ERROR]\e[00m %s" +#define ERROR_FORMAT_NC "[ERROR] %s" +#define DEBUG_FORMAT "\e[1;36m[DEBUG]\e[00m %s" +#define DEBUG_FORMAT_NC "[DEBUG] %s" +#define TRACE_FORMAT "\e[1;36m[TRACE]\e[00m %s" +#define TRACE_FORMAT_NC "[TRACE] %s" + +int logger_use_color = 1; +int logger_show_trace = 0; + +static char * +_make_format(MESSAGE_TYPE type, int add_newline, const char *fmt) { + char* msg_fmt = NULL; + const char* fmt_hdr = NULL; + int fmt_len = 0; + + switch (type) { + case INFO: + fmt_hdr = logger_use_color ? INFO_FORMAT : INFO_FORMAT_NC; + break; + case WARNING: + fmt_hdr = logger_use_color ? WARN_FORMAT : WARN_FORMAT_NC; + break; + case ERROR: + fmt_hdr = logger_use_color ? ERROR_FORMAT : ERROR_FORMAT_NC; + break; + case DEBUG: + fmt_hdr = logger_use_color ? DEBUG_FORMAT : DEBUG_FORMAT_NC; + break; + case TRACE: + fmt_hdr = logger_use_color ? TRACE_FORMAT : TRACE_FORMAT_NC; + break; + default: + fmt_hdr = "[UNKNOWN] %s"; + break; + } + + fmt_len = strlen(fmt_hdr) + strlen(fmt); + msg_fmt = (char *) malloc(fmt_len); + if (msg_fmt == NULL) { + return NULL; + } + sprintf(msg_fmt, fmt_hdr, fmt); + + if (add_newline) { + msg_fmt[fmt_len - 2] = '\n'; + msg_fmt[fmt_len - 1] = '\0'; + } + + return msg_fmt; +} + +void +log_message(MESSAGE_TYPE type, int add_newline, const char *fmt, ...) { + char *msg_fmt = NULL; + va_list list; + + if (!logger_show_trace && type == TRACE) { + return; + } + + msg_fmt = _make_format(type, add_newline, fmt); + + va_start(list, fmt); + + if (msg_fmt == NULL) { + vfprintf(stderr, fmt, list); + } + + if (type == ERROR) { + vfprintf(stderr, msg_fmt, list); + } else { + vfprintf(stdout, msg_fmt, list); + } + va_end(list); + + free(msg_fmt); +} + +void +vlog_message(MESSAGE_TYPE type, int add_newline, const char *fmt, va_list vl) { + char *msg_fmt = NULL; + + if (!logger_show_trace && type == TRACE) { + return; + } + + msg_fmt = _make_format(type, add_newline, fmt); + + if (msg_fmt == NULL) { + vfprintf(stderr, fmt, vl); + } + + if (type == ERROR) { + vfprintf(stderr, msg_fmt, vl); + } else { + vfprintf(stdout, msg_fmt, vl); + } + + free(msg_fmt); +} diff --git a/tizen_src/ewk/ubrowser/logger.h b/tizen_src/ewk/ubrowser/logger.h new file mode 100644 index 0000000..d723be2d --- /dev/null +++ b/tizen_src/ewk/ubrowser/logger.h @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2013 Peter Tworek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LOGGER_H +#define LOGGER_H + +#include + +extern "C" { + +/* Supported message types.*/ +typedef enum { + INFO, + WARNING, + ERROR, + DEBUG, + TRACE, +} MESSAGE_TYPE; + +extern int logger_use_color; +extern int logger_show_trace; + +/** + * Main logging routine. Should not be used directly. + * Please use log_ macros. + */ +void +log_message(MESSAGE_TYPE type, int add_newline, const char* format, ...); + +/** + * Logging function similar to log_message, but taking va_list as last argument. + * Useful when integration with external logging subsystems. + */ +void +vlog_message(MESSAGE_TYPE type, int add_newline, const char *fmt, va_list vl); + +/* Logging macros. */ +#define log_info(format, args...) log_message(INFO, 1, format, ## args) +#define log_warning(format, args...) log_message(WARNING, 1, format, ## args) +#define log_error(format, args...) log_message(ERROR, 1, format, ## args) +#define log_debug(format, args...) log_message(DEBUG, 1, format, ## args) +#define log_trace(format, args...) log_message(TRACE, 1, format, ## args) + +#endif /* LOGGER_H */ + +} diff --git a/tizen_src/ewk/ubrowser/main.cc b/tizen_src/ewk/ubrowser/main.cc new file mode 100644 index 0000000..ccccc04 --- /dev/null +++ b/tizen_src/ewk/ubrowser/main.cc @@ -0,0 +1,163 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include +#include +#include +#if defined(OS_TIZEN) +#include +#endif // OS_TIZEN + +#include "browser.h" +#include "logger.h" + +extern int logger_show_trace; +extern int logger_use_color; +#if defined(OS_TIZEN) +int desktop_ui = 0; +#else +int desktop_ui = 1; +#endif + +typedef struct app_data { + std::vector urls; + Browser* browser; + bool ewk_initialized; +} AppData; + +void show_help_and_exit(const char* app_name) { + printf("Usage: %s [OPTION]... [URL]...\n\n", app_name); + printf("Available options:\n"); + printf(" -v, --verbose Print verbose application logs\n"); + printf(" -n, --no-color Don't use colors in application logs\n"); + printf(" -d, --desktop Run application UI in desktop mode\n"); + printf(" -m, --mobile Run application UI in mobile mode\n"); + printf(" -h, --help Show this help message\n"); + exit(0); +} + +void parse_options(int argc, char** argv) { + int show_help = 0; + int c; + + while (1) { + static struct option long_options[] = { + {"verbose", no_argument, &logger_show_trace, 1}, + {"no-color", no_argument, &logger_use_color, 0}, + {"desktop", no_argument, &desktop_ui, 1}, + {"mobile", no_argument, &desktop_ui, 0}, + {"help", no_argument, &show_help, 1}, + {0, 0, 0, 0} + }; + + int option_index = 0; + c = getopt_long (argc, argv, "vndmh", long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 'v': + logger_show_trace = 1; + break; + case 'n': + logger_use_color = 0; + break; + case 'd': + desktop_ui = 1; + break; + case 'm': + desktop_ui = 0; + break; + case 'h': + show_help = 1; + break; + default: + // Ignore EFL or chromium specific options, + // ewk_set_arguments should handle them + continue; + } + } + + if (show_help) + show_help_and_exit(argv[0]); +} + +static bool app_create(void *data) { + AppData* app_data = static_cast(data); + + if (!ewk_init()) + return false; + + elm_config_preferred_engine_set("opengl_x11"); + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + + app_data->browser = new Browser(desktop_ui); + std::vector::iterator it = app_data->urls.begin(); + for (;it != app_data->urls.end(); ++it) + app_data->browser->CreateWindow().LoadURL(*it); + app_data->urls.clear(); + app_data->ewk_initialized = true; + return true; +} + +static void app_terminate(void* data) { + AppData* app_data = static_cast(data); + if (app_data->browser) + delete app_data->browser; + if (app_data->ewk_initialized) + ewk_shutdown(); +} + +#if defined(OS_TIZEN) && defined(TIZEN_APP) +static void app_pause(void* data) { + log_debug("Tizen uBrowser pause"); +} + +static void app_resume(void* data) { + log_debug("Tizen uBrowser resume"); +} +#endif // OS_TIZEN + +int main(int argc, char** argv) { + AppData data; + memset(&data, 0, sizeof(data)); + + for (int i = 1; i < argc; ++i) + if (argv[i][0] != '-') + data.urls.push_back(std::string(argv[i])); + + if (data.urls.empty()) + data.urls.push_back("http://www.google.com"); + + ewk_set_arguments(argc, argv); + elm_init(argc, argv); + parse_options(argc, argv); + + int ret = 0; +// Enable the section below once ubrowser is ready +// to replace mini_browser. For the code below to work +// proper manifest needs to be added to the rpm package +#if defined(OS_TIZEN) && defined(TIZEN_APP) + app_event_callback_s ops; + memset(&ops, 0, sizeof(ops)); + ops.create = app_create; + ops.terminate = app_terminate; + ops.pause = app_pause; + ops.resume = app_resume; + + ret = app_efl_main(&argc, &argv, &ops, &data); +#else + if (!app_create(&data)) + return EXIT_FAILURE; + + elm_run(); + + app_terminate(&data); +#endif + + return ret; +} diff --git a/tizen_src/ewk/ubrowser/ubrowser.gypi b/tizen_src/ewk/ubrowser/ubrowser.gypi new file mode 100644 index 0000000..ae1f578 --- /dev/null +++ b/tizen_src/ewk/ubrowser/ubrowser.gypi @@ -0,0 +1,48 @@ +{ + 'targets': [{ + 'target_name': 'ubrowser', + 'type': 'executable', + 'dependencies': [ + 'chromium-ewk', + ], + 'defines': [ + # Uncomment once uBrowser replaces mini_browser and it's xml + # manifest is shipped in the rpm package + #'TIZEN_APP=1', + ], + 'include_dirs': [ + '.', + '../efl_integration/public', + ], + 'sources': [ + 'browser.cc', + 'browser.h', + 'logger.cc', + 'logger.h', + 'main.cc', + 'window.cc', + 'window.h', + 'window_ui.h', + 'window_ui.cc', + ], + 'copies': [{ + 'destination': '<(PRODUCT_DIR)', + 'files': [ 'ubrowser.sh', ], + }], + 'conditions': [ + ['building_for_tizen==1', { + 'cflags': [ + ' zeXt!xmB4?#vQiZF%%+~Kl|mL{Hl+bs3L>%*5a}2|i7X$oDjy2SM`ZX~L^hS3jj71C z5fOqYO_l(=sEZMTAR+|;89;<=%w}WEt}z=UW>c@&RElC#sZ=VJy0w3tzUzHAcV>EK zdhX19Z+=y;@^WXUyWj0I-KS5VbNX#G3=CluOa`U^lYv8l7VsvpQ!BG4PnmD?*SrQ_ zgi$aA%mhvXK5T!V35+B>whed%_%ZOLR_1_9U5x^oJ0M82Wb1>1Hk*WGTS=uX#}7I z>`=TIxEh(O+q8fuf!nn*ulA`e5Aes4;OknMg`L;Chogo9gi&w^a09RqG1#;@0Q@s> zTbwdhA~zw+%BjG)wr&4UGXi)bjDoqqJ;3`qK5hZ4fJIuFEtND32&3Tdk*NsaPqi|; z+Si&9pdeusOhpu~&vspU5x7|^v%c?*I+**BDe3LN(ZI{?3lmBJtl?z@8J>sjPv>{A z4_RaH2Hw!h>`y8065v~mHPP-smSK-*W&Ab109u(h!YEh|oCqA=d2QSYKo|u8(}80V z`}tA848&kEm9a`$T3Nf04jo0-(!T~aAnWyekU6zY3%DByd#$%?z#2pVI(3u57XbTK zp8(83HcnA&7uq5=OyN;7+Z~zLM*F53sKL!|olbN(iIip0*S-5*vu1=!`>GT_Q8+fgGP2Cnt3DB2a&{{km#Wj1zRt84@a zqu^NJmo%N<$wk1g!zh^Jx!jq^`hQdRg-Qev=DG38e`@7zO77k9#h5HxgiRU+0__ zM!}J`u34Vzt1Ih(kNWUDDn$vj0TB;*E_O9=Rkt=AM!_k-V^r@H(oar6rnyUt7UW$) zvSH4T;cp9f4{#MdmO^0^TnYS)iPiaSJ|9NG)kO>OJ_UqPa4)jc<%4y=#obDeU0K`? ze92QigUViH^^;pE^eO;$IDU!ZBTEbT2C%r>HQOqC4*{PpSjTu_4YD%G6;$d?2e2Kp zg5sUO3wi5T_o!nEk^<$_f_021W&;7@lAal#I>17TZ||E@)rTXpj4O=5}telp`_1hAEVxnMDO1Gn^w#<9!1=NKDzmzQ6(2EXGQ1ROjT%(nFFsAGoh^Ak}Be(@T0xZ$WY|c}F zRXoo?zUbo$w52Q#03XPz5Ed2y+d=<9J_pWSNJPym31vsf9(i82AUefC{&0D)f^Z$O z3aOjZ>cd)@i?cl7LjXDx5M*H!aJE+F^_X&}BXfR{&VLf=eD4`J!YDWi_$l@BVQe8; zK%8?B6jB1M3-?7i9(@t9XTKg(?vWJl{3nnUX{DrJu^B$*(G_Y{F+)fIO{NEma5cTN zT_v#!_(bOpUME(lo~2mlZ$#ew#PIH-SRu&th4+EWtn%taZUL}P9@l1k%mAN>^MSW! z@j*F1Bjw35bj=^_f9}-;BSFFH2-S2u6I5ms{ zr}=UTnb;PmH9@}4Pg|Vh`4e2-~b)julkK$ zajdPX{vMoaUBVN|EC6=CPMfRmba?ZpB90?jmyvO7s6le3I;4baGmK;pPbAL>Fr8$( z{CAOz*s)m2e3W8q{cgONdJFQasvFQn>WV6l0GyI=?J3|2hvZ1hQp(B0e|s)35B<*i zk;aG8ZpgD8d~(d^uOddC#Px6(1(zWX48GZ8!_BLtRLf%yPE5NY^JY*O1;0eRQajm> z1Y#yG!EE0Ae`90%K9cmnuZ+5^^; z_n{nhHTdD(Nf)zrN;?8)JF?t!dFCDlE5qk_#!|S`tZR4Ch#nvON!1M)M0~upWu$`5!=R>vuau(s0cImd zx7LAvoIWz{C^`bv9;ksDY6Q<*;_08F$eeU zYVX(#={{1~`Q*N&W9V`TfIZi@j;UJDrXm5byP)?{FH`s^@Xe$f^6CKBQ@<2x0H3r@ zs8ukBdUZa)%Cs=OJki0!NOGt;(ms>73KmpUZxX3VEAos07g4X=c-`F8?-)TF_b|7g zbvp2ZOV-dl0x&%OTRcqki!;_Eu-)-3IZhR zsc!55dS+hlMHV~2`M6~Us}n~6zX+q?Dr8AixIi25vW)t!gqCDUk(*@-$dVYcP7EXG z7C&dr*SQFzU?_}&Pa~=E>)QDn$nf@q<6eNZ{QZIIoj!c97WgM5WBHaOLy66Zb_|jf z^Kw!`t!u!?v@$PbdBAlF_$=e2^Fd-3+HnhSg;B5pIk@62`*SFgaCsWi`E|B=bh0vQ z=YzWdd@5_f1Hu&Gw5l87ft}<`Tc7$?+oZ!;B7J(Mf^R65Yqc`F@;vA=te@+6A4slT zMM^M2gI88+Wme^V*rj97%TV4@t;`zW#+>bG$i`;mT;<#(3P2bIBe>6zJAk|F?+*ei z^Ea!(fjz*dik^v-HUfMScSZ5`_E9j_;Bqe!GCgXCuPo{qk!0NCZ9%Rc%(G8~s?M~ah?GkqJ}SWLosi$#eW0ZvS~ z*2#-m*P-_Q^MH_g9ky6E_5)XGWxndek0Fk@PIe8njPg{fm1)^neuen2HH>8k@KLSI z{i$~rBu)Tg6AN~cnld&Ct;{RHUjWNV$!0ZycoO)aHK~_QoB$*y81A63LZ_A4t(Cb3 z84WfSEpLE%3%CM@(^q^FCjc(Kf1`0nz~@0L^D=Ne5_d4s3`Z-0qqH&)mO0<|BF@h5 zq5zKiYzTloaqPY@3RVKwAx00^(P$7^3*2IbzY^j)+C@80Jue_Hc3Suv@LuE)O7Fr} zF&hvstG}$W^C5l&aOvFA&&ab&#&3pEa2Mj3G9QV;9Yp`c7VrXa2k=b4hx$0;1i)nu z?psnwJ2k8VR@rEui-8LmjI=O2fQNwR670r)S6XDi9dWg}h}1B=5bI2sXz zc}UD+T~gF)(0CARr)R35Z4yTd3LMSS@uBZ}h^`}?0GCzp*NuHfyT zNu=u&Ekq~UiEL?)0$Y($ax1X0s9RQ*^b`QC%>FP6)*^3I5@!M5@!qP8SiRs@WI7l^ ztZ7%cxJujHK9i8|qWy0Rc>(qV`|C2wl|j;+`55T}a2^#3Ko|wHkY(Zp$ltOXN!7C4 zwbShUJYi!QVq*hsJmBw1SFDbAJUiG6HePQo($SqRYfmGNl8w_z1`>lq!zlP6={W&b z180}vtkBh#DZnL&E#R1rOQT56LNDRp6OA+hn1vkwmZm7Ziku?uRUx!T&Yyv-`~Qlu zXW;Dv?nHu72385Hn$+;{FbY-xS2~on7wM2?F2~9y)Hi~3`aDF*>}79w1X!Szc|C7E z4T6gRi~zqvvTeAq57EMZf{YB?;)Z5h_6)?L_hDc*GQ9U1aau^?BdwKL@7R`x6kHQT z%mRK+$}yxd?BkDX=)Ja#VPu!j#hQ2kdE=LAWhSz}Kq)w93lF2G^SFDOU^A@?G25=Jaeq@tn1kvR8*q{GFHcqwy go13A%p`j-HACcs(e02bp)Bpeg07*qoM6N<$g7+=>zyJUM literal 0 HcmV?d00001 diff --git a/tizen_src/ewk/ubrowser/ubrowser.sh b/tizen_src/ewk/ubrowser/ubrowser.sh new file mode 100755 index 0000000..218a817 --- /dev/null +++ b/tizen_src/ewk/ubrowser/ubrowser.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +SCRIPTDIR=$(cd $(dirname $0); pwd -P) +OUT_DIR=$(echo $SCRIPTDIR | grep -Po "(?<=/)out\..*?(?=/)") +BUILD_MODE=Release + +. $SCRIPTDIR/../../build/common.sh + +_LIBDIR=lib +if [ "$(getHostArch)" == "x64" ]; then + _LIBDIR=lib64 +fi + +if echo $SCRIPTDIR | grep -q "Debug/efl_webview_app"; then + BUILD_MODE=Debug +fi + +CHROMIUM_EFL_LIBDIR=$(cd $SCRIPTDIR/lib; pwd -P) +CHROMIUM_EFL_DEPENDENCIES_LIBDIR=$(cd $SCRIPTDIR/../Dependencies/Root/$_LIBDIR; pwd -P) + +export LD_LIBRARY_PATH=$CHROMIUM_EFL_DEPENDENCIES_LIBDIR:$CHROMIUM_EFL_LIBDIR:${LD_LIBRARY_PATH} +echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" + +export ELM_ACCEL=hw + +exec ${SCRIPTDIR}/ubrowser "$@" diff --git a/tizen_src/ewk/ubrowser/ubrowser.xml b/tizen_src/ewk/ubrowser/ubrowser.xml new file mode 100644 index 0000000..761889b --- /dev/null +++ b/tizen_src/ewk/ubrowser/ubrowser.xml @@ -0,0 +1,11 @@ + + + + SRPOL + Small reference browser application for chromium-efl port + + /opt/share/icons/ubrowser.png + + + + diff --git a/tizen_src/ewk/ubrowser/window.cc b/tizen_src/ewk/ubrowser/window.cc new file mode 100644 index 0000000..23e2bcb --- /dev/null +++ b/tizen_src/ewk/ubrowser/window.cc @@ -0,0 +1,311 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "window.h" + +#include +#include +#include +#include +#include + +#include "browser.h" +#include "logger.h" +#include "window_ui.h" + +Window::Window(Browser& browser, int width, int height) + : browser_(browser) { + window_ = elm_win_util_standard_add( + "ubrowser", "uBrowser"); + evas_object_resize(window_, width, height); + elm_win_autodel_set(window_, EINA_TRUE); + + Evas_Object* conform = elm_conformant_add(window_); + evas_object_size_hint_weight_set(conform, + EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(window_, conform); + evas_object_show(conform); + + Evas_Object *box = elm_box_add(window_); + elm_object_content_set(conform, box); + evas_object_show(box); + + ui_ = new WindowUI(*this, browser_); + + elm_box_pack_end(box, ui_->GetURLBar()); + evas_object_show(ui_->GetURLBar()); + + web_view_elm_host_ = elm_bg_add(window_); + evas_object_size_hint_align_set( + web_view_elm_host_, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set( + web_view_elm_host_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_focus_allow_set(web_view_elm_host_, EINA_TRUE); + elm_box_pack_end(box, web_view_elm_host_); + evas_object_show(web_view_elm_host_); + + elm_box_pack_end(box, ui_->GetNavBar()); + evas_object_show(ui_->GetNavBar()); + + elm_object_focus_set(web_view_elm_host_, EINA_TRUE); + evas_object_smart_callback_add(web_view_elm_host_, "focused", + &Window::OnHostFocusedIn, this); + evas_object_smart_callback_add(web_view_elm_host_, "unfocused", + &Window::OnHostFocusedOut, this); + + Evas* evas = evas_object_evas_get(window_); + web_view_ = ewk_view_add(evas); + evas_object_resize(web_view_, width, height); + elm_object_part_content_set(web_view_elm_host_, "overlay", web_view_); + + evas_object_smart_callback_add(web_view_, "title,changed", + &Window::OnTitleChanged, this); + evas_object_smart_callback_add(web_view_, "url,changed", + &Window::OnURLChanged, this); + evas_object_smart_callback_add(web_view_, "load,progress,started", + &Window::OnLoadStarted, this); + evas_object_smart_callback_add(web_view_, "load,progress,finished", + &Window::OnLoadFinished, this); + evas_object_smart_callback_add(web_view_, "create,window", + &Window::OnNewWindowRequest, this); + evas_object_smart_callback_add(web_view_, "console,message", + &Window::OnConsoleMessage, NULL); + evas_object_smart_callback_add(web_view_, "policy,newwindow,decide", + &Window::OnNewWindowPolicyDecide, NULL); + evas_object_smart_callback_add(window_, "delete,request", + &Window::OnWindowDelRequest, this); + evas_object_smart_callback_add(window_, "back,forward,lsit,changed", + &Window::OnBackForwardListChanged, this); + + if (elm_win_wm_rotation_supported_get(window_)) { + static const int rots[] = {0, 90, 270}; + elm_win_wm_rotation_available_rotations_set( + window_, rots, (sizeof(rots) / sizeof(int))); + evas_object_smart_callback_add(window_, "wm,rotation,changed", + &Window::OnOrientationChanged, this); + } + + evas_object_show(window_); +} + +Window::~Window() { + assert(!window_); + delete ui_; +} + +void Window::LoadURL(std::string url) { + const static std::string http = "http"; + const static std::string about = "about:"; + if (url.compare(0, 1, "/") == 0) { + url = "file://" + url; + } else if (url.compare(0, http.length(), http) != 0 && + url.compare(0, about.length(), about) != 0) { + url = "http://" + url; + } + log_info("Loading URL: %s", url.c_str()); + ewk_view_url_set(web_view_, url.c_str()); + ui_->OnURLChanged(url.c_str()); +} + +const char* Window::GetURL() const { + return ewk_view_url_get(web_view_); +} + +void Window::Activate() { + log_trace("%s", __PRETTY_FUNCTION__); + elm_win_activate(window_); +} + +void Window::Close() { + log_trace("%s", __PRETTY_FUNCTION__); + evas_object_del(window_); + browser_.OnWindowDestroyed(Id()); + window_ = NULL; +} + +void Window::Show() { + log_trace("%s", __PRETTY_FUNCTION__); + evas_object_show(window_); +} + +void Window::Hide() { + log_trace("%s", __PRETTY_FUNCTION__); + evas_object_hide(window_); +} + +void Window::Back() { + log_trace("%s", __PRETTY_FUNCTION__); + ewk_view_back(web_view_); +} + +void Window::Forward() { + log_trace("%s", __PRETTY_FUNCTION__); + ewk_view_forward(web_view_); +} + +void Window::Reload() { + log_trace("%s", __PRETTY_FUNCTION__); + ewk_view_reload(web_view_); +} + +void Window::Stop() { + log_trace("%s", __PRETTY_FUNCTION__); + ewk_view_stop(web_view_); +} + +void Window::SetUserAgent(const char* new_ua) { + log_trace("%s: %s", __PRETTY_FUNCTION__, new_ua); + ewk_view_user_agent_set(web_view_, new_ua); +} + +const char* Window::GetUserAgent() const { + return ewk_view_user_agent_get(web_view_); +} + +void Window::FakeRotate() { + log_trace("%s", __PRETTY_FUNCTION__); + int x, y, width, height; + evas_object_geometry_get(window_, &x, &y, &width, &height); + evas_object_move(window_, x, y); + evas_object_resize(window_, height, width); + if (width > height) + ewk_view_orientation_send(web_view_, 0); + else + ewk_view_orientation_send(web_view_, 90); +} + +void Window::Resize(int width, int height) { + int x, y; + log_trace("%s: %dx%d", __PRETTY_FUNCTION__, width, height); + evas_object_geometry_get(window_, &x, &y, 0, 0); + evas_object_move(window_, x, y); + evas_object_resize(window_, width, height); + ewk_view_orientation_send(web_view_, 0); +} + +void Window::EnableTouchEvents(bool enable) { + log_trace("%s: %d", __PRETTY_FUNCTION__, enable); + ewk_view_touch_events_enabled_set(web_view_, enable); +} + +void Window::EnableMouseEvents(bool enable) { + log_trace("%s: %d", __PRETTY_FUNCTION__, enable); + ewk_view_mouse_events_enabled_set(web_view_, enable); +} + +double Window::GetScale() const { + log_trace("%s", __PRETTY_FUNCTION__); + return ewk_view_scale_get(web_view_); +} + +void Window::SetScale(double scale) { + log_trace("%s", __PRETTY_FUNCTION__); + ewk_view_scale_set(web_view_, scale, 0, 0); +} + +Window::IdType Window::Id() const { + return window_; +} + +void Window::OnHostFocusedIn(void* data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + Window* thiz = static_cast(data); + evas_object_focus_set(thiz->web_view_, EINA_TRUE); +} + +void Window::OnHostFocusedOut(void* data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + Window* thiz = static_cast(data); + evas_object_focus_set(thiz->web_view_, EINA_FALSE); +} + +void Window::OnWindowDelRequest(void* data, Evas_Object*, void*) { + Window* thiz = static_cast(data); + thiz->browser_.OnWindowDestroyed(thiz->Id()); +} + +void Window::OnNewWindowRequest(void *data, Evas_Object*, void* out_view) { + log_trace("%s", __PRETTY_FUNCTION__); + Window* thiz = static_cast(data); + Window& new_window = thiz->browser_.CreateWindow(); + *static_cast(out_view) = new_window.web_view_; +} + +void Window::OnTitleChanged(void *data, Evas_Object *obj, void *arg) { + Window* thiz = static_cast(data); + elm_win_title_set(thiz->window_, static_cast(arg)); + log_trace("%s: %s", __PRETTY_FUNCTION__, static_cast(arg)); + thiz->browser_.OnWindowTitleChanged(thiz->Id(), static_cast(arg)); +} + +void Window::OnURLChanged(void *data, Evas_Object *obj, void *arg) { + Window* thiz = static_cast(data); + log_trace("%s: %s", __PRETTY_FUNCTION__, static_cast(arg)); + elm_win_title_set(thiz->window_, static_cast(arg)); + thiz->ui_->OnURLChanged(static_cast(arg)); +} + +void Window::OnLoadStarted(void* data, Evas_Object*, void*) { + Window* thiz = static_cast(data); + log_trace("%s", __PRETTY_FUNCTION__); + thiz->browser_.OnWindowLoadStarted(thiz->Id()); + thiz->ui_->OnLoadingStarted(); +} + +void Window::OnLoadFinished(void* data, Evas_Object*, void*) { + Window* thiz = static_cast(data); + log_trace("%s", __PRETTY_FUNCTION__); + thiz->browser_.OnWindowLoadFinished(thiz->Id()); + thiz->ui_->OnLoadingFinished(); +} + +void Window::OnConsoleMessage(void*, Evas_Object*, void* event_info) { + Ewk_Console_Message* msg = static_cast(event_info); + + MESSAGE_TYPE type; + switch (ewk_console_message_level_get(msg)) { + case EWK_CONSOLE_MESSAGE_LEVEL_ERROR: + type = ERROR; + break; + case EWK_CONSOLE_MESSAGE_LEVEL_WARNING: + type = WARNING; + break; + case EWK_CONSOLE_MESSAGE_LEVEL_DEBUG: + type = DEBUG; + break; + default: + type = INFO; + } + + log_message(type, true, "[JS Console] [%s:%d] %s", + ewk_console_message_source_get(msg), + ewk_console_message_line_get(msg), + ewk_console_message_text_get(msg)); +} + +void Window::OnOrientationChanged(void* data, Evas_Object *obj, void* event) { + Window* thiz = static_cast(data); + log_trace("%s", __PRETTY_FUNCTION__); + + int rotation = elm_win_rotation_get(thiz->window_); + // ewk_view_orientation_send expects angles: 0, 90, -90, 180. + if (rotation == 270) + rotation = -90; + ewk_view_orientation_send(thiz->web_view_, rotation); +} + +void Window::OnNewWindowPolicyDecide(void*, Evas_Object*, void* policy) { + log_trace("%s", __PRETTY_FUNCTION__); + Ewk_Policy_Decision *policy_decision = static_cast(policy); + const char* url = ewk_policy_decision_url_get(policy_decision); + log_info("Allowing new window for: %s", url); + ewk_policy_decision_use(policy_decision); +} + +void Window::OnBackForwardListChanged(void* data, Evas_Object*, void* policy) { + log_trace("%s", __PRETTY_FUNCTION__); + Window* thiz = static_cast(data); + thiz->ui_->EnableBackButton(ewk_view_back_possible(thiz->web_view_)); + thiz->ui_->EnableForwardButton(ewk_view_forward_possible(thiz->web_view_)); +} diff --git a/tizen_src/ewk/ubrowser/window.h b/tizen_src/ewk/ubrowser/window.h new file mode 100644 index 0000000..0377908 --- /dev/null +++ b/tizen_src/ewk/ubrowser/window.h @@ -0,0 +1,65 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef _WINDOW_H_ +#define _WINDOW_H_ + +#include +#include + +class Browser; +class WindowUI; + +class Window { + public: + typedef void* IdType; + + Window(Browser&, int width, int height); + ~Window(); + + Evas_Object* GetEvasObject() const { return window_; }; + + void LoadURL(std::string url); + const char* GetURL() const; + void Activate(); + void Close(); + void Show(); + void Hide(); + void Back(); + void Forward(); + void Reload(); + void Stop(); + void SetUserAgent(const char* new_ua); + const char* GetUserAgent() const; + void FakeRotate(); + void Resize(int width, int height); + void EnableTouchEvents(bool); + void EnableMouseEvents(bool); + double GetScale() const; + void SetScale(double); + + IdType Id() const; + + private: + static void OnHostFocusedIn(void* data, Evas_Object*, void*); + static void OnHostFocusedOut(void* data, Evas_Object*, void*); + static void OnWindowDelRequest(void* data, Evas_Object*, void*); + static void OnNewWindowRequest(void *data, Evas_Object*, void*); + static void OnTitleChanged(void*, Evas_Object*, void*); + static void OnURLChanged(void*, Evas_Object*, void*); + static void OnLoadStarted(void*, Evas_Object*, void*); + static void OnLoadFinished(void*, Evas_Object*, void*); + static void OnConsoleMessage(void*, Evas_Object*, void*); + static void OnOrientationChanged(void*, Evas_Object*, void*); + static void OnNewWindowPolicyDecide(void*, Evas_Object*, void*); + static void OnBackForwardListChanged(void*, Evas_Object*, void*); + + Browser& browser_; + WindowUI* ui_; + Evas_Object* window_; + Evas_Object* web_view_; + Evas_Object* web_view_elm_host_; +}; + +#endif // _WINDOW_H_ diff --git a/tizen_src/ewk/ubrowser/window_ui.cc b/tizen_src/ewk/ubrowser/window_ui.cc new file mode 100644 index 0000000..d8924e7 --- /dev/null +++ b/tizen_src/ewk/ubrowser/window_ui.cc @@ -0,0 +1,331 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "window_ui.h" + +#include +#include +#include + +#include "browser.h" +#include "logger.h" +#include "window.h" + +namespace { +static std::string kDefaultNewWindowURL = "http://www.google.com"; +static double kMinViewScale = 1; +static double kMaxViewScale = 4; +static double kViewScaleDelta = 0.1; +} + +WindowUI::WindowUI(Window& window, Browser& browser) + : window_(window) + , browser_(browser) + , is_loading_(false) { + navbar_ = elm_box_add(window_.GetEvasObject()); + elm_box_horizontal_set(navbar_, EINA_TRUE); + elm_box_homogeneous_set(navbar_, EINA_TRUE); + evas_object_size_hint_weight_set(navbar_, EVAS_HINT_EXPAND, 0.0f); + evas_object_size_hint_align_set(navbar_, EVAS_HINT_FILL, EVAS_HINT_FILL); + + AddButton(navbar_, "file", "New Window", &WindowUI::OnCreateWindow); + back_button_ = AddButton(navbar_, "arrow_left", "Back", &WindowUI::OnBack); + forward_button_ = AddButton(navbar_, "arrow_right", "Forward", + &WindowUI::OnForward); + stop_reload_button_ = AddButton(navbar_, "refresh", "Reload", + &WindowUI::OnStopOrReload); + AddButton(navbar_, "arrow_up", "More Actions", + &WindowUI::OnShowExtraActionsMenu); + + urlbar_ = elm_box_add(window_.GetEvasObject()); + elm_box_horizontal_set(urlbar_, EINA_TRUE); + evas_object_size_hint_weight_set(urlbar_, EVAS_HINT_EXPAND, 0.0f); + evas_object_size_hint_align_set(urlbar_, EVAS_HINT_FILL, EVAS_HINT_FILL); + + progress_bar_ = elm_progressbar_add(window_.GetEvasObject()); + elm_object_style_set(progress_bar_, "wheel"); + elm_progressbar_pulse_set(progress_bar_, EINA_TRUE); + elm_progressbar_pulse(progress_bar_, EINA_FALSE); + elm_box_pack_end(urlbar_, progress_bar_); + evas_object_show(progress_bar_); + + url_entry_ = elm_entry_add(urlbar_); + elm_entry_single_line_set(url_entry_, EINA_TRUE); + elm_entry_scrollable_set(url_entry_, EINA_TRUE); + elm_entry_input_panel_layout_set(url_entry_, ELM_INPUT_PANEL_LAYOUT_URL); + evas_object_size_hint_weight_set(url_entry_, EVAS_HINT_EXPAND, 1.0f); + evas_object_size_hint_align_set(url_entry_, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_smart_callback_add(url_entry_, "activated", OnURLEntered, this); + elm_box_pack_end(urlbar_, url_entry_); + evas_object_show(url_entry_); + + Evas_Object* separator = elm_separator_add(urlbar_); + elm_separator_horizontal_set(separator, EINA_TRUE); + elm_box_pack_end(urlbar_, separator); + evas_object_show(separator); + + // FIXME: Uncomment once "back,forward,lsit,changed" EWK callback works + //EnableBackButton(false); + //EnableForwardButton(false); + + extra_actions_menu_ = CreateExtraActionsMenu(window_.GetEvasObject()); +} + +void WindowUI::OnURLChanged(const char* url) { + log_trace("%s: %s", __PRETTY_FUNCTION__, url); + elm_object_text_set(url_entry_, url); +} + +void WindowUI::OnLoadingStarted() { + log_trace("%s", __PRETTY_FUNCTION__); + elm_progressbar_pulse(progress_bar_, EINA_TRUE); + Evas_Object* icon = elm_object_part_content_get(stop_reload_button_, "icon"); + elm_icon_standard_set(icon, "close"); + if (browser_.IsDesktop()) + elm_object_text_set(stop_reload_button_, "Stop"); + is_loading_ = true; +} + +void WindowUI::OnLoadingFinished() { + log_trace("%s", __PRETTY_FUNCTION__); + elm_progressbar_pulse(progress_bar_, EINA_FALSE); + Evas_Object* icon = elm_object_part_content_get(stop_reload_button_, "icon"); + elm_icon_standard_set(icon, "refresh"); + if (browser_.IsDesktop()) + elm_object_text_set(stop_reload_button_, "Reload"); + is_loading_ = false; +} + +void WindowUI::EnableBackButton(bool enable) { + elm_object_disabled_set(back_button_, !enable); +} + +void WindowUI::EnableForwardButton(bool enable) { + elm_object_disabled_set(forward_button_, !enable); +} + +Evas_Object* WindowUI::AddButton(Evas_Object* parent, + const char* icon, const char* label, Evas_Smart_Cb cb) { + Evas_Object *bt = elm_button_add(parent); + evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, 0.5); + if (label && browser_.IsDesktop()) + elm_object_text_set(bt, label); + if (icon) { + Evas_Object* icon_elm = elm_icon_add(bt); + elm_icon_standard_set(icon_elm, icon); + elm_object_part_content_set(bt, "icon", icon_elm); + } + evas_object_smart_callback_add(bt, "clicked", cb, this); + elm_box_pack_end(parent, bt); + evas_object_show(bt); + + return bt; +} + +Evas_Object* WindowUI::CreateExtraActionsMenu(Evas_Object* parent) { + Evas_Object* menu = elm_menu_add(parent); + elm_menu_item_add(menu, NULL, NULL, + "Override User Agent String", &WindowUI::OnUAOverride, this); + + if (browser_.IsDesktop()) { + elm_menu_item_add(menu, NULL, NULL, + "Show Web Inspector", &WindowUI::OnInspectorShow, this); + elm_menu_item_add(menu, NULL, NULL, "Simulate screen rotation", + &WindowUI::OnRotate, this); + + Elm_Object_Item* resize = elm_menu_item_add(menu, NULL, NULL, "Resize", + NULL, NULL); + elm_menu_item_add(menu, resize, NULL, "360x640", + &WindowUI::OnResize, new std::pair("360x640", this)); + elm_menu_item_add(menu, resize, NULL, "800x600", + &WindowUI::OnResize, new std::pair("800x600", this)); + elm_menu_item_add(menu, resize, NULL, "1024x768", + &WindowUI::OnResize, new std::pair("1024x768", this)); + elm_menu_item_add(menu, resize, NULL, "1280x720", + &WindowUI::OnResize, new std::pair("1280x720", this)); + } + + Elm_Object_Item* input = elm_menu_item_add(menu, NULL, NULL, "Input event type", + NULL, NULL); + elm_menu_item_add(menu, input, NULL, "Mouse", + &WindowUI::OnSelectMouseInput, this); + elm_menu_item_add(menu, input, NULL, "Touch", + &WindowUI::OnSelectTouchInput, this); + +#if defined(OS_TIZEN) + // Techincally those functions change page scale factor, not zoom in/out. + // The code was borrowed from mini_browser app. On desktop support for + // page scale factor is disabled so don't show the options. + elm_menu_item_add(menu, NULL, NULL, + "Zoom in", &WindowUI::OnZoomIn, this); + elm_menu_item_add(menu, NULL, NULL, + "Zoom out", &WindowUI::OnZoomOut, this); +#endif // OS_TIZEN + + return menu; +} + +namespace { +static void _ClosePopup(void *data, Evas_Object*, void*) { + Evas_Object* popup = static_cast(data); + evas_object_del(popup); +} +} + +void WindowUI::ShowTextEntryPopup(const char* title, + const char* initial_content, Evas_Smart_Cb cb) { + Evas_Object* popup = elm_popup_add(window_.GetEvasObject()); + elm_object_part_text_set(popup, "title,text", title); + elm_popup_orient_set(popup, ELM_POPUP_ORIENT_CENTER); + + log_trace("%s: (%s, %s)", __PRETTY_FUNCTION__, title, initial_content); + + Evas_Object* entry = elm_entry_add(popup); + elm_entry_single_line_set(entry, EINA_TRUE); + elm_entry_scrollable_set(entry, EINA_TRUE); + elm_entry_input_panel_layout_set(entry, ELM_INPUT_PANEL_LAYOUT_URL); + evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, 0.0f); + evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_smart_callback_add(entry, "activated", cb, + new std::pair(entry, this)); + + elm_object_part_content_set(popup, "default", entry); + if (initial_content) { + elm_object_text_set(entry, initial_content); + elm_entry_cursor_end_set(entry); + } + + Evas_Object* btn = elm_button_add(popup); + elm_object_text_set(btn, "OK"); + evas_object_smart_callback_add(btn, "clicked", cb, + new std::pair(entry, this)); + elm_object_part_content_set(popup, "button1", btn); + + btn = elm_button_add(popup); + elm_object_text_set(btn, "Cancel"); + evas_object_smart_callback_add(btn, "clicked", _ClosePopup, popup); + elm_object_part_content_set(popup, "button2", btn); + + evas_object_show(popup); +} + +void WindowUI::OnCreateWindow(void *data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + WindowUI *thiz = static_cast(data);; + if (thiz->browser_.IsDesktop()) { + thiz->browser_.CreateWindow().LoadURL(kDefaultNewWindowURL); + } else { + thiz->browser_.ActivateToolboxWindow(); + } +} + +void WindowUI::OnBack(void *data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + static_cast(data)->window_.Back(); +} + +void WindowUI::OnForward(void *data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + static_cast(data)->window_.Forward(); +} + +void WindowUI::OnStopOrReload(void *data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + WindowUI* thiz = static_cast(data); + if (thiz->is_loading_) + thiz->window_.Stop(); + else + thiz->window_.Reload(); +} + +void WindowUI::OnShowExtraActionsMenu(void *data, Evas_Object* obj, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + WindowUI* thiz = static_cast(data); + int x, y; + evas_object_geometry_get(obj, &x, &y, 0, 0); + elm_menu_move(thiz->extra_actions_menu_, x, y); + evas_object_show(thiz->extra_actions_menu_); +} + +void WindowUI::OnURLEntered(void *data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + WindowUI* thiz = static_cast(data); + thiz->window_.LoadURL(elm_object_text_get(thiz->url_entry_)); + elm_object_focus_set(thiz->url_entry_, EINA_FALSE); +} + +void WindowUI::OnUAOverride(void* data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + WindowUI *thiz = static_cast(data); + const char* ua = thiz->window_.GetUserAgent(); + thiz->ShowTextEntryPopup("User Agent Override", ua, + &WindowUI::OnUAOverrideEntered); +} + +void WindowUI::OnUAOverrideEntered(void* data, Evas_Object*, void*) { + std::pair* p = + static_cast*>(data); + p->second->window_.SetUserAgent(elm_object_text_get(p->first)); + Evas_Object* content = elm_object_parent_widget_get(p->first); + Evas_Object* popup = elm_object_parent_widget_get(content); + popup = elm_object_parent_widget_get(popup); + evas_object_del(popup); + delete p; +} + +void WindowUI::OnInspectorShow(void* data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + static_cast(data)->browser_.ShowInspectorWindow(); +} + +void WindowUI::OnRotate(void* data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + static_cast(data)->window_.FakeRotate(); +} + +void WindowUI::OnResize(void* data, Evas_Object*, void*) { + std::pair* pr = + static_cast*>(data); + int width, height; + sscanf(pr->first, "%dx%d", &width, &height); + log_trace("%s %dx%d", __PRETTY_FUNCTION__, width, height); + pr->second->window_.Resize(width, height); +} + +void WindowUI::OnSelectMouseInput(void* data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + WindowUI *thiz = static_cast(data); + thiz->window_.EnableTouchEvents(false); + thiz->window_.EnableMouseEvents(true); +} + +void WindowUI::OnSelectTouchInput(void* data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + WindowUI *thiz = static_cast(data); + thiz->window_.EnableTouchEvents(true); + thiz->window_.EnableMouseEvents(false); +} + +namespace { +inline void _change_zoom(Window& win, double delta) { + double scale = win.GetScale(); + if (scale >= kMinViewScale && scale < kMaxViewScale) { + scale += delta; + win.SetScale(scale); + } +} +} + +void WindowUI::OnZoomIn(void* data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + WindowUI *thiz = static_cast(data); + _change_zoom(thiz->window_, kViewScaleDelta); +} + +void WindowUI::OnZoomOut(void* data, Evas_Object*, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + WindowUI *thiz = static_cast(data); + _change_zoom(thiz->window_, -kViewScaleDelta); +} diff --git a/tizen_src/ewk/ubrowser/window_ui.h b/tizen_src/ewk/ubrowser/window_ui.h new file mode 100644 index 0000000..8f1b6c94 --- /dev/null +++ b/tizen_src/ewk/ubrowser/window_ui.h @@ -0,0 +1,69 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef _WINDOW_UI_H_ +#define _WINDOW_UI_H_ + +#include + +class Window; +class Browser; + +class WindowUI { + public: + WindowUI(Window&, Browser&); + + Evas_Object* GetNavBar() const { return navbar_; } + Evas_Object* GetURLBar() const { return urlbar_; } + + void OnURLChanged(const char* url); + void OnLoadingStarted(); + void OnLoadingFinished(); + + void EnableBackButton(bool); + void EnableForwardButton(bool); + + private: + Evas_Object* AddButton(Evas_Object*, const char*, + const char*, Evas_Smart_Cb); + Evas_Object* CreateExtraActionsMenu(Evas_Object*); + void ShowTextEntryPopup(const char* title, + const char* initial_content, Evas_Smart_Cb); + + // Nav bar callbacks + static void OnCreateWindow(void *data, Evas_Object*, void*); + static void OnBack(void *data, Evas_Object*, void*); + static void OnForward(void *data, Evas_Object*, void*); + static void OnStopOrReload(void *data, Evas_Object*, void*); + static void OnShowExtraActionsMenu(void *data, Evas_Object*, void*); + + // URL bar callbacks + static void OnURLEntered(void *data, Evas_Object*, void*); + + // Extra actions callbacks + static void OnUAOverride(void* data, Evas_Object*, void*); + static void OnUAOverrideEntered(void* data, Evas_Object*, void*); + static void OnInspectorShow(void* data, Evas_Object*, void*); + static void OnRotate(void* data, Evas_Object*, void*); + static void OnResize(void* data, Evas_Object*, void*); + static void OnSelectMouseInput(void* data, Evas_Object*, void*); + static void OnSelectTouchInput(void* data, Evas_Object*, void*); + static void OnZoomIn(void* data, Evas_Object*, void*); + static void OnZoomOut(void* data, Evas_Object*, void*); + + Window& window_; + Browser& browser_; + Evas_Object* navbar_; + Evas_Object* urlbar_; + Evas_Object* url_entry_; + Evas_Object* extra_actions_menu_; + Evas_Object* stop_reload_button_; + Evas_Object* progress_bar_; + Evas_Object* forward_button_; + Evas_Object* back_button_; + + bool is_loading_; +}; + +#endif // _WINDOW_UI_H_ diff --git a/tizen_src/packaging/chromium-efl.manifest b/tizen_src/packaging/chromium-efl.manifest index 7feb459..6392d25 100644 --- a/tizen_src/packaging/chromium-efl.manifest +++ b/tizen_src/packaging/chromium-efl.manifest @@ -58,5 +58,6 @@ + diff --git a/tizen_src/packaging/chromium-efl.spec b/tizen_src/packaging/chromium-efl.spec index 31fa967..7f31ec0 100755 --- a/tizen_src/packaging/chromium-efl.spec +++ b/tizen_src/packaging/chromium-efl.spec @@ -231,7 +231,7 @@ build/prebuild/ninja %{_smp_mflags} -C"%{OUTPUT_FOLDER}" \ %if 0%{?build_ewk_unittests} ewk_unittests \ %endif - chromium-efl efl_webprocess chromium-ewk efl_webview_app mini_browser + chromium-efl efl_webprocess chromium-ewk efl_webview_app mini_browser ubrowser %if 0%{?_enable_unittests} ninja %{_smp_mflags} -C"%{OUTPUT_FOLDER}" angle_unittests env_chromium_unittests cacheinvalidation_unittests \ @@ -286,6 +286,7 @@ install -m 0644 "%{OUTPUT_FOLDER}"/resources/*.edj "%{buildroot}%{CHROMIUM_DAT install -m 0755 "%{OUTPUT_FOLDER}"/efl_webview_app "%{buildroot}"%{_bindir} install -m 0755 "%{OUTPUT_FOLDER}"/mini_browser "%{buildroot}"%{_bindir} +install -m 0755 "%{OUTPUT_FOLDER}"/ubrowser "%{buildroot}"%{_bindir} install -m 0644 "%{OUTPUT_FOLDER}"/pkgconfig/*.pc "%{buildroot}"%{_libdir}/pkgconfig/ install -m 0644 ewk/efl_integration/public/*.h "%{buildroot}"%{_includedir}/chromium-ewk/ @@ -335,6 +336,7 @@ smack_reload.sh %{CHROMIUM_DATA_DIR}/themes/*.edj %{_bindir}/efl_webview_app %{_bindir}/mini_browser +%{_bindir}/ubrowser /opt/share/packages/chromium-efl.xml /opt/share/icons/mini-browser.png %{CHROMIUM_DATA_DIR}/locale/* -- 2.7.4