From a32332dcc4aa34590e953d84535992e9b823c95a Mon Sep 17 00:00:00 2001 From: Jakub Izydorczyk Date: Thu, 9 Oct 2014 14:42:03 +0200 Subject: [PATCH] [Tizen] Refactor XWalkLauncher for usage of RESET event. After this change execute xwalk-launcher on Tizen will cause initialization of app core and launch of g_main_loop. Application will be actually launched after xwalk-launcher receives RESET event from platform. BUG=XWALK-2779 --- application/tools/linux/dbus_connection.cc | 21 -- application/tools/linux/dbus_connection.h | 12 - .../tools/linux/dbus_object_manager.cc | 219 ++++++++++++ application/tools/linux/dbus_object_manager.h | 82 +++++ .../tools/linux/xwalk_application_tools.gyp | 7 +- application/tools/linux/xwalk_launcher.cc | 95 +++++ application/tools/linux/xwalk_launcher.h | 49 +++ .../tools/linux/xwalk_launcher_main.cc | 329 +++--------------- .../tools/linux/xwalk_launcher_tizen.cc | 121 ++++--- .../tools/linux/xwalk_launcher_tizen.h | 43 ++- application/tools/tizen/xwalk_backend.cc | 1 - 11 files changed, 618 insertions(+), 361 deletions(-) delete mode 100644 application/tools/linux/dbus_connection.cc delete mode 100644 application/tools/linux/dbus_connection.h create mode 100644 application/tools/linux/dbus_object_manager.cc create mode 100644 application/tools/linux/dbus_object_manager.h create mode 100644 application/tools/linux/xwalk_launcher.cc create mode 100644 application/tools/linux/xwalk_launcher.h diff --git a/application/tools/linux/dbus_connection.cc b/application/tools/linux/dbus_connection.cc deleted file mode 100644 index 2e7f3c3f2d..0000000000 --- a/application/tools/linux/dbus_connection.cc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2013 Intel Corporation. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "xwalk/application/tools/linux/dbus_connection.h" - -GDBusConnection* get_session_bus_connection(GError** error) { -#if defined(OS_TIZEN_MOBILE) - // In Tizen the session bus is created in /run/user/app/dbus/user_bus_socket - // but this information isn't set in DBUS_SESSION_BUS_ADDRESS, neither when - // logging via 'sdb shell' and changing user to 'app', nor when an application - // is launched. - return g_dbus_connection_new_for_address_sync( - "unix:path=/run/user/app/dbus/user_bus_socket", - GDBusConnectionFlags(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT - | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), - NULL, NULL, error); -#else - return g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, error); -#endif -} diff --git a/application/tools/linux/dbus_connection.h b/application/tools/linux/dbus_connection.h deleted file mode 100644 index 022eee551f..0000000000 --- a/application/tools/linux/dbus_connection.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2013 Intel Corporation. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef XWALK_APPLICATION_TOOLS_LINUX_DBUS_CONNECTION_H_ -#define XWALK_APPLICATION_TOOLS_LINUX_DBUS_CONNECTION_H_ - -#include - -GDBusConnection* get_session_bus_connection(GError** error); - -#endif // XWALK_APPLICATION_TOOLS_LINUX_DBUS_CONNECTION_H_ diff --git a/application/tools/linux/dbus_object_manager.cc b/application/tools/linux/dbus_object_manager.cc new file mode 100644 index 0000000000..feccbcc1e8 --- /dev/null +++ b/application/tools/linux/dbus_object_manager.cc @@ -0,0 +1,219 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "xwalk/application/tools/linux/dbus_object_manager.h" + +#include "base/message_loop/message_loop.h" + +namespace { + +const char kServiceName[] = "org.crosswalkproject.Runtime1"; +const char kRunningManagerIface[] = "org.crosswalkproject.Running.Manager1"; +const char kRunningAppIface[] = "org.crosswalkproject.Running.Application1"; +const char kRunningManagerDBusPath[] = "/running1"; +const char kEPChannelCreatedSignalName[] = "EPChannelCreated"; + +struct Properties : public dbus::PropertySet { + dbus::Property app_id; + + Properties(dbus::ObjectProxy* object_proxy, + const std::string& interface_name, + PropertyChangedCallback property_changed_callback) + : PropertySet(object_proxy, interface_name, property_changed_callback) { + RegisterProperty("AppID", &app_id); + } +}; + +} // namespace + +DBusObjectManager::DBusObjectManager(dbus::Bus* bus, + base::MessageLoop* main_loop) + : bus_(bus), + main_loop_(main_loop), + weak_ptr_factory_(this) { + ConnectToApplicationManager(); +} + +bool DBusObjectManager::Launch(const std::string& appid_or_url, + int launcher_pid, bool fullscreen, bool remote_debugging) { + if (!running_proxy_) + return false; + dbus::MethodCall method_call( + kRunningManagerIface, "Launch"); + dbus::MessageWriter writer(&method_call); + writer.AppendString(appid_or_url); + writer.AppendUint32(launcher_pid); + writer.AppendBool(fullscreen); + writer.AppendBool(remote_debugging); + scoped_ptr response( + running_proxy_->CallMethodAndBlock(&method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); + if (!response.get()) + return false; + if (!response->GetErrorName().empty()) { + LOG(ERROR) << "Error during call to 'Launch': " + << response->GetErrorName(); + return false; + } + + dbus::MessageReader reader(response.get()); + dbus::ObjectPath running_application_path; + if (!reader.PopObjectPath(&running_application_path)) { + LOG(WARNING) << "Failed to create app proxy."; + } else { + app_proxy_ = bus_->GetObjectProxy(kServiceName, running_application_path); + if (app_proxy_) + ConnectToApplicationSignal(kEPChannelCreatedSignalName); + } + return true; +} + +std::pair DBusObjectManager::GetEPChannel() const { + std::pair fd; + if (!app_proxy_) { + fd.second = -1; + return fd; + } + dbus::MethodCall method_call(kRunningAppIface, "GetEPChannel"); + scoped_ptr response = app_proxy_->CallMethodAndBlock( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); + const std::string& error = response->GetErrorName(); + if (!error.empty()) { + LOG(ERROR) << "Error during call to 'GetEPChannel': " + << error; + fd.second = -1; + return fd; + } + dbus::MessageReader reader(response.release()); + dbus::FileDescriptor extension_process_fd_; + if (!reader.PopString(&fd.first) || + !reader.PopFileDescriptor(&extension_process_fd_)) { + LOG(ERROR) << "Couldn't get EP Channel"; + fd.second = -1; + return fd; + } + extension_process_fd_.CheckValidity(); + fd.second = extension_process_fd_.TakeValue(); + return fd; +} + +bool DBusObjectManager::Suspend() { + if (!app_proxy_) + return false; + dbus::MethodCall method_call(kRunningAppIface, "Suspend"); + scoped_ptr response = app_proxy_->CallMethodAndBlock( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); + if (!response->GetErrorName().empty()) { + LOG(ERROR) << "Error during call to 'Suspend': " + << response->GetErrorName(); + return false; + } + return true; +} + +bool DBusObjectManager::Resume() { + if (!app_proxy_) + return false; + dbus::MethodCall method_call(kRunningAppIface, "Resume"); + scoped_ptr response = app_proxy_->CallMethodAndBlock( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); + if (!response->GetErrorName().empty()) { + LOG(ERROR) << "Error during call to 'Resume': " + << response->GetErrorName(); + return false; + } + return true; +} + +void DBusObjectManager::OnOwnershipCallback(const std::string& service_name, + bool success) { + LOG(WARNING) << "Couldn't get ownership of D-Bus service name: " + << service_name << "."; +} + +void DBusObjectManager::ConnectToApplicationManager() { + running_apps_manager_ = bus_->GetObjectManager(kServiceName, + dbus::ObjectPath(kRunningManagerDBusPath)); + running_apps_manager_->RegisterInterface(kRunningAppIface, this); + running_proxy_ = bus_->GetObjectProxy(kServiceName, + dbus::ObjectPath(kRunningManagerDBusPath)); +} + +void DBusObjectManager::ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) { +} + +void DBusObjectManager::ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) { + if (object_path != app_proxy_->object_path()) + return; + LOG(INFO) << "Application '" << object_path.value() + << "' disappeared, exiting."; + main_loop_->QuitNow(); +} + +dbus::PropertySet* DBusObjectManager::CreateProperties( + dbus::ObjectProxy *object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) { + Properties* properties = new Properties( + object_proxy, interface_name, + base::Bind(&DBusObjectManager::OnPropertyChanged, + base::Unretained(this), object_path)); + return static_cast(properties); +} + +void DBusObjectManager::OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& name) { + if (!running_apps_manager_) + ConnectToApplicationManager(); +} + +void DBusObjectManager::ConnectToApplicationSignal( + const std::string& signal_name) { + DCHECK(app_proxy_); + app_proxy_->ConnectToSignal(kRunningAppIface, signal_name, + base::Bind(&DBusObjectManager::OnAppSignal, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&DBusObjectManager::OnAppSignalConnected, + weak_ptr_factory_.GetWeakPtr())); +} + +bool DBusObjectManager::IsApplicationRunning(const std::string& app_id) { + std::vector objects = running_apps_manager_->GetObjects(); + bool is_running = false; + for (dbus::ObjectPath obj : objects) { + Properties* properties = + static_cast( + running_apps_manager_->GetProperties( + obj, kRunningAppIface)); + if (!properties) + continue; + if (properties->app_id.value() == app_id) { + is_running = true; + break; + } + } + LOG(INFO) << "Application " << app_id << " is " + << (is_running ? "running." : "not running."); + return is_running; +} + +void DBusObjectManager::OnAppSignal(dbus::Signal* signal) { + std::string signal_name = signal->GetMember(); + if (signal_name == kEPChannelCreatedSignalName) { + if (observer_) + observer_->OnEPChannelCreated(); + } else { + LOG(INFO) << "Unknown signal received: " << signal_name; + } +} + +void DBusObjectManager::OnAppSignalConnected( + const std::string& interface_name, + const std::string& signal_name, + bool success) { + if (!success) + LOG(WARNING) << "Failed to connect signal: " << signal_name; +} diff --git a/application/tools/linux/dbus_object_manager.h b/application/tools/linux/dbus_object_manager.h new file mode 100644 index 0000000000..ccb9fb267b --- /dev/null +++ b/application/tools/linux/dbus_object_manager.h @@ -0,0 +1,82 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_APPLICATION_TOOLS_LINUX_DBUS_OBJECT_MANAGER_H_ +#define XWALK_APPLICATION_TOOLS_LINUX_DBUS_OBJECT_MANAGER_H_ + +#include +#include +#include +#include + +#include "base/macros.h" +#include "base/threading/thread.h" +#include "base/values.h" +#include "dbus/bus.h" +#include "dbus/exported_object.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "dbus/property.h" + +class DBusObjectManager : public dbus::ObjectManager::Interface { + public: + class Observer { + public: + virtual void OnEPChannelCreated() = 0; + + protected: + virtual ~Observer() {} + }; + + DBusObjectManager(dbus::Bus* bus, base::MessageLoop* main_loop); + + bool Launch(const std::string& appid_or_url, int launcher_pid, + bool fullscreen, bool remote_debugging); + std::pair GetEPChannel() const; + bool Suspend(); + bool Resume(); + + bool IsApplicationRunning(const std::string& app_id); + + void SetObserver(Observer* observer) { observer_ = observer; } + + private: + void OnOwnershipCallback(const std::string& service_name, bool success); + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override; + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override; + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override; + + void OnPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& name); + + void ConnectToApplicationManager(); + void ConnectToApplicationSignal(const std::string& signal_name); + void OnAppSignal(dbus::Signal* signal); + void OnAppSignalConnected(const std::string& interface_name, + const std::string& signal_name, + bool success); + + scoped_refptr bus_; + dbus::ObjectManager* running_apps_manager_; + dbus::ObjectProxy* running_proxy_; + dbus::ObjectProxy* app_proxy_; + + // this is needed for exit events which come via dbus interface + base::MessageLoop* main_loop_; + + base::WeakPtrFactory weak_ptr_factory_; + + Observer* observer_; + + DISALLOW_COPY_AND_ASSIGN(DBusObjectManager); +}; + +#endif // XWALK_APPLICATION_TOOLS_LINUX_DBUS_OBJECT_MANAGER_H_ diff --git a/application/tools/linux/xwalk_application_tools.gyp b/application/tools/linux/xwalk_application_tools.gyp index a70f1b41ad..6b3f08b997 100644 --- a/application/tools/linux/xwalk_application_tools.gyp +++ b/application/tools/linux/xwalk_application_tools.gyp @@ -12,10 +12,11 @@ '../../../build/system.gyp:gio', '../../../extensions/extensions.gyp:xwalk_extensions', '../../../application/common/xwalk_application_common.gypi:xwalk_application_common_lib', + '../../../dbus/xwalk_dbus.gyp:xwalk_dbus' ], 'sources': [ - 'dbus_connection.cc', - 'dbus_connection.h', + 'dbus_object_manager.cc', + 'dbus_object_manager.h', 'xwalk_extension_process_launcher.cc', 'xwalk_extension_process_launcher.h', 'xwalk_launcher_main.cc', @@ -27,6 +28,8 @@ '../../../build/system.gyp:tizen_appcore_common' ], 'sources': [ + 'xwalk_launcher.cc', + 'xwalk_launcher.h', 'xwalk_launcher_tizen.cc', 'xwalk_launcher_tizen.h', '../tizen/xwalk_tizen_user.cc', diff --git a/application/tools/linux/xwalk_launcher.cc b/application/tools/linux/xwalk_launcher.cc new file mode 100644 index 0000000000..04964d593b --- /dev/null +++ b/application/tools/linux/xwalk_launcher.cc @@ -0,0 +1,95 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2014 Samsung Electronics Co., Ltd 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 "dbus/object_proxy.h" + +#include "base/logging.h" + +#include "xwalk/application/tools/linux/xwalk_launcher.h" + +namespace { + +const char xwalk_service_name[] = "org.crosswalkproject.Runtime1"; +const char xwalk_running_path[] = "/running1"; +const char xwalk_running_manager_iface[] = + "org.crosswalkproject.Running.Manager1"; +const char xwalk_running_app_iface[] = + "org.crosswalkproject.Running.Application1"; + +} // namespace + +XWalkLauncher::XWalkLauncher(bool query_running, base::MessageLoop* main_loop) + : ep_launcher_(nullptr), + query_running_(query_running), + main_loop_(main_loop) { + base::Thread::Options thread_options; + thread_options.message_loop_type = base::MessageLoop::TYPE_IO; + dbus_thread_.reset(new base::Thread("Crosswalk D-Bus thread")); + dbus_thread_->StartWithOptions(thread_options); + + dbus::Bus::Options options; +#if defined (OS_TIZEN_MOBILE) + options.bus_type = dbus::Bus::CUSTOM_ADDRESS; + options.address.assign("unix:path=/run/user/app/dbus/user_bus_socket"); +#endif + options.bus_type = dbus::Bus::SESSION; + options.connection_type = dbus::Bus::PRIVATE; + options.dbus_task_runner = dbus_thread_->message_loop_proxy(); + dbus::Bus* bus = new dbus::Bus(options); + bus->Connect(); + bus->GetManagedObjects(); + + dbus_object_manager_.reset(new DBusObjectManager(bus, main_loop)); + dbus_object_manager_->SetObserver(this); +} + +XWalkLauncher::~XWalkLauncher() { +} + +int XWalkLauncher::Launch(const std::string& appid_or_url, bool fullscreen, + bool remote_debugging, int argc, char* argv[]) { + appid_or_url_ = appid_or_url; + fullscreen_ = fullscreen; + remote_debugging_ = remote_debugging; + + // Query app. + if (query_running_) { + return dbus_object_manager_->IsApplicationRunning(appid_or_url_); + } + + return !LaunchApplication(); +} + +int XWalkLauncher::LaunchApplication() { + ep_launcher_.reset(new XWalkExtensionProcessLauncher()); + + launcher_pid_ = getpid(); + if (!dbus_object_manager_->Launch(appid_or_url_, launcher_pid_, + fullscreen_, remote_debugging_)) + return 1; + return InitExtensionProcessChannel(); +} + +bool XWalkLauncher::InitExtensionProcessChannel() { + if (ep_launcher_->is_started()) + return false; + + // Need to call method via DBus to get EP channel + std::pair fd = dbus_object_manager_->GetEPChannel(); + if (fd.first.empty() || fd.second < 0) + return false; + ep_launcher_->Launch(fd.first, fd.second); + return true; +} + +void XWalkLauncher::OnEPChannelCreated() { + InitExtensionProcessChannel(); +} diff --git a/application/tools/linux/xwalk_launcher.h b/application/tools/linux/xwalk_launcher.h new file mode 100644 index 0000000000..e4c0533e30 --- /dev/null +++ b/application/tools/linux/xwalk_launcher.h @@ -0,0 +1,49 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_APPLICATION_TOOLS_LINUX_XWALK_LAUNCHER_H_ +#define XWALK_APPLICATION_TOOLS_LINUX_XWALK_LAUNCHER_H_ + +#include +#include + +#include "base/threading/thread.h" +#include "dbus/bus.h" +#include "dbus/message.h" + +#include "xwalk/application/tools/linux/dbus_object_manager.h" +#include "xwalk/application/tools/linux/xwalk_extension_process_launcher.h" + +class XWalkLauncher : public DBusObjectManager::Observer { + public: + XWalkLauncher(bool query_running, base::MessageLoop* main_loop); + virtual ~XWalkLauncher(); + virtual int Launch(const std::string& appid_or_url, bool fullscreen, + bool remote_debugging, int argc = 0, + char* argv[] = nullptr); + + protected: + int LaunchApplication(); + + std::unique_ptr ep_launcher_; + + unsigned int launcher_pid_; + std::string appid_or_url_; + bool fullscreen_; + bool remote_debugging_; + bool query_running_; + + base::MessageLoop* main_loop_; + + std::unique_ptr dbus_object_manager_; + + private: + bool InitExtensionProcessChannel(); + virtual void OnEPChannelCreated() override; + + std::unique_ptr dbus_thread_; +}; + +#endif // XWALK_APPLICATION_TOOLS_LINUX_XWALK_LAUNCHER_H_ diff --git a/application/tools/linux/xwalk_launcher_main.cc b/application/tools/linux/xwalk_launcher_main.cc index 46c956b752..8ea14b781e 100644 --- a/application/tools/linux/xwalk_launcher_main.cc +++ b/application/tools/linux/xwalk_launcher_main.cc @@ -1,272 +1,48 @@ // Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2014 Samsung Electronics Co., Ltd 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 -#include -#include -#include - #include -#include -#include -#include "xwalk/application/tools/linux/dbus_connection.h" -#include "xwalk/application/tools/linux/xwalk_extension_process_launcher.h" +#include + +#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_pump.h" +#include "base/message_loop/message_pump_glib.h" +#include "base/run_loop.h" + +#include "xwalk/application/tools/linux/xwalk_launcher.h" #if defined(OS_TIZEN) -#include "url/gurl.h" #include "xwalk/application/tools/linux/xwalk_launcher_tizen.h" -#include "xwalk/application/tools/tizen/xwalk_tizen_user.h" #endif -static const char* xwalk_service_name = "org.crosswalkproject.Runtime1"; -static const char* xwalk_running_path = "/running1"; -static const char* xwalk_running_manager_iface = - "org.crosswalkproject.Running.Manager1"; -static const char* xwalk_running_app_iface = - "org.crosswalkproject.Running.Application1"; +namespace { -static char* application_object_path; +int g_argc; +char** g_argv; +gboolean query_running = FALSE; +gboolean fullscreen = FALSE; +gboolean remote_debugging = FALSE; +gchar** cmd_appid_or_url; +char* application_object_path; -static GMainLoop* mainloop; -static GDBusConnection* g_connection; -static GDBusObjectManager* g_running_apps_manager; -static XWalkExtensionProcessLauncher* ep_launcher = NULL; +} // namespace -static int g_argc; -static char** g_argv; -static gboolean query_running = FALSE; -static gboolean fullscreen = FALSE; -static gboolean remote_debugging = FALSE; -static gchar** cmd_appid_or_url; - -static GOptionEntry entries[] = { +static const GOptionEntry entries[] { { "running", 'r', 0, G_OPTION_ARG_NONE, &query_running, - "Check whether the application is running", NULL }, + "Check whether the application is running", nullptr }, { "fullscreen", 'f', 0, G_OPTION_ARG_NONE, &fullscreen, - "Run the application as fullscreen", NULL }, + "Run the application as fullscreen", nullptr }, { "debugging_port", 'd', 0, G_OPTION_ARG_NONE, &remote_debugging, - "Enable remote debugging for the application", NULL }, - { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &cmd_appid_or_url, - "ID of the application to be launched or URL to open", NULL }, - { NULL } + "Enable remote debugging for the application", nullptr }, + { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, + &cmd_appid_or_url, + "ID of the application to be launched or URL to open", nullptr }, + { nullptr } }; -static void object_removed(GDBusObjectManager* manager, GDBusObject* object, - gpointer user_data) { - const char* path = g_dbus_object_get_object_path(object); - - if (g_strcmp0(path, application_object_path)) - return; - - fprintf(stderr, "Application '%s' disappeared, exiting.\n", path); - - delete ep_launcher; - g_main_loop_quit(mainloop); -} - -static void on_app_properties_changed(GDBusProxy* proxy, - GVariant* changed_properties, - GStrv invalidated_properties, - gpointer user_data) { - const char* interface = g_dbus_proxy_get_interface_name(proxy); - - fprintf(stderr, "properties changed %s\n", interface); - - if (g_variant_n_children(changed_properties) == 0) - return; - - if (g_strcmp0(interface, xwalk_running_app_iface)) - return; - - GVariantIter* iter; - const gchar* key; - GVariant* value; - - g_variant_get(changed_properties, "a{sv}", &iter); - - while (g_variant_iter_loop(iter, "{&sv}", &key, &value)) { - if (g_strcmp0(key, "State")) - continue; - - const gchar* state = g_variant_get_string(value, NULL); - - fprintf(stderr, "Application state %s\n", state); - } -} - -static gboolean init_extension_process_channel(GDBusProxy* app_proxy) { - if (ep_launcher->is_started()) - return FALSE; - - // Get the client socket file descriptor from fd_list. The reply will - // contains an index to the list. - GUnixFDList* fd_list; - GVariant* res = g_dbus_proxy_call_with_unix_fd_list_sync( - app_proxy, "GetEPChannel", NULL, G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &fd_list, NULL, NULL); - if (!res || g_variant_n_children(res) != 2) - return FALSE; - - const gchar* channel_id = - g_variant_get_string(g_variant_get_child_value(res, 0), NULL); - if (!channel_id || !strlen(channel_id)) - return FALSE; - - gint32 client_fd_idx = - g_variant_get_handle(g_variant_get_child_value(res, 1)); - int client_fd = g_unix_fd_list_get(fd_list, client_fd_idx, NULL); - - ep_launcher->Launch(channel_id, client_fd); - return TRUE; -} - -static void on_app_signal(GDBusProxy* proxy, - gchar* sender_name, - gchar* signal_name, - GVariant* parameters, - gpointer user_data) { - if (!strcmp(signal_name, "EPChannelCreated")) { - init_extension_process_channel(proxy); - } else { - fprintf(stderr, "Unkown signal received: %s\n", signal_name); - } -} - -static int query_application_running(const char* app_id) { - GList* objects = g_dbus_object_manager_get_objects(g_running_apps_manager); - GList* it; - bool is_running = FALSE; - - for (it = objects; it; it = it->next) { - GDBusObject* object = reinterpret_cast(it->data); - GDBusInterface* iface = g_dbus_object_get_interface( - object, - xwalk_running_app_iface); - if (!iface) - continue; - - GDBusProxy* proxy = G_DBUS_PROXY(iface); - GVariant* id_variant; - id_variant = g_dbus_proxy_get_cached_property(proxy, "AppID"); - if (!id_variant) { - g_object_unref(iface); - continue; - } - - const gchar* id; - g_variant_get(id_variant, "s", &id); - if (!strcmp(app_id, id)) { - is_running = TRUE; - break; - } - - g_object_unref(iface); - } - const char* str = is_running ? "running" : "not running"; - g_print("Application %s is %s.\n", app_id, str); - - g_list_free_full(objects, g_object_unref); - return is_running ? 0 : 1; -} - -static void launch_application(const char* appid_or_url, - gboolean fullscreen, - gboolean remote_debugging) { - ep_launcher = new XWalkExtensionProcessLauncher(); - GError* error = NULL; - g_signal_connect(g_running_apps_manager, "object-removed", - G_CALLBACK(object_removed), NULL); - - GDBusProxy* running_proxy = g_dbus_proxy_new_sync( - g_connection, - G_DBUS_PROXY_FLAGS_NONE, NULL, xwalk_service_name, - xwalk_running_path, xwalk_running_manager_iface, NULL, &error); - if (!running_proxy) { - g_print("Couldn't create proxy for '%s': %s\n", xwalk_running_manager_iface, - error->message); - g_error_free(error); - exit(1); - } - - unsigned int launcher_pid = getpid(); - - GVariant* result = g_dbus_proxy_call_sync(running_proxy, "Launch", - g_variant_new("(subb)", appid_or_url, launcher_pid, fullscreen, - remote_debugging), - G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); - if (!result) { - fprintf(stderr, "Couldn't call 'Launch' method: %s\n", error->message); - exit(1); - } - - g_variant_get(result, "(o)", &application_object_path); - fprintf(stderr, "Application launched with path '%s'\n", - application_object_path); - - GDBusProxy* app_proxy = g_dbus_proxy_new_sync( - g_connection, - G_DBUS_PROXY_FLAGS_NONE, NULL, xwalk_service_name, - application_object_path, xwalk_running_app_iface, NULL, &error); - if (!app_proxy) { - g_print("Couldn't create proxy for '%s': %s\n", xwalk_running_app_iface, - error->message); - g_error_free(error); - exit(1); - } - - g_signal_connect(app_proxy, "g-properties-changed", - G_CALLBACK(on_app_properties_changed), NULL); - - mainloop = g_main_loop_new(NULL, FALSE); - g_signal_connect(app_proxy, "g-signal", G_CALLBACK(on_app_signal), NULL); - -#if defined(OS_TIZEN) - char name[128]; - snprintf(name, sizeof(name), "xwalk-%s", appid_or_url); - - if (xwalk_appcore_init(g_argc, g_argv, name, app_proxy)) { - fprintf(stderr, "Failed to initialize appcore"); - exit(1); - } -#endif - - init_extension_process_channel(app_proxy); - g_main_loop_run(mainloop); -} - -void connect_to_application_manager() { - GError* error = NULL; - g_connection = get_session_bus_connection(&error); - if (!g_connection) { - fprintf(stderr, "Couldn't get the session bus connection: %s\n", - error->message); - exit(1); - } - - g_running_apps_manager = - g_dbus_object_manager_client_new_sync( - g_connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, - xwalk_service_name, xwalk_running_path, - NULL, NULL, NULL, NULL, &error); - if (!g_running_apps_manager) { - fprintf(stderr, "Service '%s' does could not be reached: %s\n", - xwalk_service_name, error->message); - exit(1); - } -} - int main(int argc, char** argv) { - GError* error = NULL; - char* appid_or_url; - - g_argc = argc; - g_argv = argv; - #if !GLIB_CHECK_VERSION(2, 36, 0) // g_type_init() is deprecated on GLib since 2.36. g_type_init(); @@ -274,42 +50,43 @@ int main(int argc, char** argv) { #if defined(OS_TIZEN) if (xwalk_tizen_check_group_users()) - exit(1); + return 1; #endif + base::MessageLoop msg_loop( + make_scoped_ptr(new base::MessagePumpGlib())); + + g_argc = argc; + g_argv = argv; + GError* error = nullptr; GOptionContext* context = g_option_context_new("- Crosswalk Application Launcher"); - g_option_context_add_main_entries(context, entries, NULL); + g_option_context_add_main_entries(context, entries, nullptr); if (!g_option_context_parse(context, &argc, &argv, &error)) { - fprintf(stderr, "Option parsing failed: %s\n", error->message); + LOG(ERROR) << "Option parsing failed: " << error->message; exit(1); } - connect_to_application_manager(); - - // Launch app. - if (!strcmp(basename(argv[0]), "xwalk-launcher")) { - if (cmd_appid_or_url == NULL) { - fprintf(stderr, "No AppID informed, nothing to do.\n"); - return 0; - } - appid_or_url = strdup(cmd_appid_or_url[0]); -#if defined(OS_TIZEN) - if (GURL(appid_or_url).spec().empty() - && xwalk_change_cmdline(argc, argv, appid_or_url)) + std::string appid_or_url; + if (!strcmp(basename(g_argv[0]), "xwalk-launcher")) { + if (!cmd_appid_or_url) { + LOG(ERROR) << "No AppID informed, nothing to do."; exit(1); -#endif + } + appid_or_url = std::string(cmd_appid_or_url[0]); } else { - appid_or_url = strdup(basename(argv[0])); + appid_or_url = std::string(basename(g_argv[0])); } - - // Query app. - if (query_running) { - return query_application_running(appid_or_url); - } - - launch_application(appid_or_url, fullscreen, remote_debugging); - free(appid_or_url); - return 0; + std::unique_ptr launcher; +#if defined(OS_TIZEN) + launcher.reset(new XWalkLauncherTizen(query_running, &msg_loop)); +#else + launcher.reset(new XWalkLauncher(query_running, &msg_loop)); +#endif + int result = launcher->Launch(appid_or_url, fullscreen, remote_debugging, + argc, argv); + if (!result) + msg_loop.Run(); + return result; } diff --git a/application/tools/linux/xwalk_launcher_tizen.cc b/application/tools/linux/xwalk_launcher_tizen.cc index a26b05325f..8aa67b77db 100644 --- a/application/tools/linux/xwalk_launcher_tizen.cc +++ b/application/tools/linux/xwalk_launcher_tizen.cc @@ -1,40 +1,31 @@ // Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2014 Samsung Electronics Co., Ltd 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 "xwalk/application/tools/linux/xwalk_launcher_tizen.h" + +#include +#include #include -#include #include -#include -#include +#include -#include "xwalk/application/common/id_util.h" -#include "xwalk/application/tools/linux/xwalk_launcher_tizen.h" +#include -enum app_event { - AE_UNKNOWN, - AE_CREATE, - AE_TERMINATE, - AE_PAUSE, - AE_RESUME, - AE_RESET, - AE_LOWMEM_POST, - AE_MEM_FLUSH, - AE_MAX -}; +#include "base/logging.h" +#include "url/gurl.h" // Private struct from appcore-internal, necessary to get events from // the system. struct ui_ops { void* data; - void (*cb_app)(enum app_event evnt, void* data, bundle* b); + void (*cb_app)(app_event evnt, void* data, bundle* b); }; -static struct ui_ops appcore_ops; +namespace { -static const char* event2str(enum app_event event) { +const char* Event2Str(app_event event) { switch (event) { case AE_UNKNOWN: return "AE_UNKNOWN"; @@ -59,33 +50,68 @@ static const char* event2str(enum app_event event) { return "INVALID EVENT"; } -static void application_event_cb(enum app_event event, void* data, bundle* b) { - fprintf(stderr, "event '%s'\n", event2str(event)); - GDBusProxy* app_proxy = reinterpret_cast(data); +ui_ops app_ops; + +} // namespace - if (!app_proxy) { - fprintf(stderr, "Invalid DBus proxy."); - return; +XWalkLauncherTizen::XWalkLauncherTizen(bool query_running, + base::MessageLoop* main_loop) + : XWalkLauncher(query_running, main_loop) { +} + +int XWalkLauncherTizen::Launch(const std::string& appid_or_url, bool fullscreen, + bool remote_debugging, int argc, char* argv[]) { + appid_or_url_ = appid_or_url; + fullscreen_ = fullscreen; + remote_debugging_ = remote_debugging; + // Query app. + if (query_running_) { + return dbus_object_manager_->IsApplicationRunning(appid_or_url_); } + std::string name = "xwalk-" + appid_or_url_; + + if (XwalkAppcoreInit(name, argc, argv)) { + LOG(ERROR) << "Failed to initialize appcore."; + return 1; + } + if (GURL(appid_or_url_).spec().empty() + && XwalkChangeCmdline(appid_or_url_, argc, argv)) + return 1; + return 0; +} + +bool XWalkLauncherTizen::Suspend() { + return dbus_object_manager_->Suspend(); +} + +bool XWalkLauncherTizen::Resume() { + return dbus_object_manager_->Resume(); +} + +void XWalkLauncherTizen::application_event_cb(app_event event, + void* data, bundle* b) { + XWalkLauncherTizen* xwalk_launcher = static_cast(data); + LOG(INFO) << "event '" << Event2Str(event) << "'"; switch (event) { case AE_UNKNOWN: case AE_CREATE: break; case AE_TERMINATE: - exit(0); + xwalk_launcher->main_loop_->QuitNow(); break; case AE_PAUSE: - g_dbus_proxy_call( - app_proxy, "Suspend", NULL, - G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + if (!xwalk_launcher->Suspend()) + LOG(ERROR) << "Suspending application failed"; break; case AE_RESUME: - g_dbus_proxy_call( - app_proxy, "Resume", NULL, - G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + if (!xwalk_launcher->Resume()) + LOG(ERROR) << "Resuming application failed"; break; case AE_RESET: + if (!xwalk_launcher->LaunchApplication()) + xwalk_launcher->main_loop_->QuitNow(); + break; case AE_LOWMEM_POST: case AE_MEM_FLUSH: case AE_MAX: @@ -93,34 +119,37 @@ static void application_event_cb(enum app_event event, void* data, bundle* b) { } } -int xwalk_appcore_init( - int argc, char** argv, const char* name, GDBusProxy* app_proxy) { - appcore_ops.cb_app = application_event_cb; - appcore_ops.data = app_proxy; - - return appcore_init(name, &appcore_ops, argc, argv); +int XWalkLauncherTizen::XwalkAppcoreInit(const std::string& name, + int argc, char* argv[]) { + app_ops.cb_app = application_event_cb; + app_ops.data = this; + return appcore_init(name.c_str(), &app_ops, argc, argv); } -int xwalk_change_cmdline(int argc, char** argv, const char* app_id) { +int XWalkLauncherTizen::XwalkChangeCmdline(const std::string& app_id, + int argc, char* argv[]) { // Change /proc//cmdline to app exec path. See XWALK-1722 for details. pkgmgrinfo_appinfo_h handle; - char* exec_path = NULL; + char* exec_path = nullptr; // todo : add is_admin - if (pkgmgrinfo_appinfo_get_usr_appinfo(app_id, + if (pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle) != PMINFO_R_OK || pkgmgrinfo_appinfo_get_exec(handle, &exec_path) != PMINFO_R_OK || !exec_path) { - if (pkgmgrinfo_appinfo_get_appinfo(app_id, &handle) != PMINFO_R_OK || + if (pkgmgrinfo_appinfo_get_appinfo(app_id.c_str(), &handle) != + PMINFO_R_OK || pkgmgrinfo_appinfo_get_exec(handle, &exec_path) != PMINFO_R_OK || !exec_path) { - fprintf(stderr, "Couldn't find exec path for application: %s\n", app_id); + LOG(ERROR) << "Couldn't find exec path for application: " << app_id; return -1; } } + // zeros g_argv_ for (int i = 0; i < argc; ++i) memset(argv[i], 0, strlen(argv[i])); - strncpy(argv[0], exec_path, strlen(exec_path)+1); + + strncpy(argv[0], exec_path, strlen(exec_path) + 1); pkgmgrinfo_appinfo_destroy_appinfo(handle); return 0; } diff --git a/application/tools/linux/xwalk_launcher_tizen.h b/application/tools/linux/xwalk_launcher_tizen.h index 75237bdd42..a0c8f3fd2b 100644 --- a/application/tools/linux/xwalk_launcher_tizen.h +++ b/application/tools/linux/xwalk_launcher_tizen.h @@ -1,13 +1,50 @@ // Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef XWALK_APPLICATION_TOOLS_LINUX_XWALK_LAUNCHER_TIZEN_H_ #define XWALK_APPLICATION_TOOLS_LINUX_XWALK_LAUNCHER_TIZEN_H_ -int xwalk_appcore_init(int argc, char** argv, - const char* name, GDBusProxy* app_proxy); +#include +#include -int xwalk_change_cmdline(int argc, char** argv, const char* app_id); +#include +#include + +#include "base/message_loop/message_loop.h" + +#include "xwalk/application/common/id_util.h" +#include "xwalk/application/tools/linux/xwalk_launcher.h" +#include "xwalk/application/tools/tizen/xwalk_tizen_user.h" + +// Private enum from appcore-internal +extern "C" enum app_event { + AE_UNKNOWN, + AE_CREATE, + AE_TERMINATE, + AE_PAUSE, + AE_RESUME, + AE_RESET, + AE_LOWMEM_POST, + AE_MEM_FLUSH, + AE_MAX +}; + +class XWalkLauncherTizen : public XWalkLauncher { + public: + XWalkLauncherTizen(bool query_running, base::MessageLoop* main_loop); + int Launch(const std::string& appid_or_url, bool fullscreen, + bool remote_debugging, int argc, char* argv[]); + bool Suspend(); + bool Resume(); + + private: + static void application_event_cb(app_event event, void* data, bundle* b); + int XwalkAppcoreInit(const std::string& name, int argc, char* argv[]); + int XwalkChangeCmdline(const std::string& app_id, int argc, char* argv[]); + + base::MessageLoop* main_loop_; +}; #endif // XWALK_APPLICATION_TOOLS_LINUX_XWALK_LAUNCHER_TIZEN_H_ diff --git a/application/tools/tizen/xwalk_backend.cc b/application/tools/tizen/xwalk_backend.cc index 862a47b51b..148155bc0c 100644 --- a/application/tools/tizen/xwalk_backend.cc +++ b/application/tools/tizen/xwalk_backend.cc @@ -16,7 +16,6 @@ #include "base/path_service.h" #include "xwalk/application/common/id_util.h" #include "xwalk/application/common/tizen/application_storage.h" -#include "xwalk/application/tools/linux/dbus_connection.h" #include "xwalk/application/tools/tizen/xwalk_package_installer.h" #include "xwalk/application/tools/tizen/xwalk_tizen_user.h" #include "xwalk/runtime/common/xwalk_paths.h"