From: Youngsoo Choi Date: Wed, 4 Jan 2017 09:01:10 +0000 (+0900) Subject: Assure proper termination using context session X-Git-Tag: accepted/tizen/3.0.m2/common/20170111.094130^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Faccepted%2Ftizen_3.0.m2_wearable;p=platform%2Fframework%2Fweb%2Fcrosswalk-tizen.git Assure proper termination using context session Current main loop quits when closing window callback is called. Btw, it does not assure proper termination of changing watch face because context session stops too early and callback can not be called and then dead lock happens. So, this CL extends the main loop until all the context sessions are finished and covers following termination scenarios. * h/w back key * exit pop up menu * exit command |pkgcmd -k| * uninstall command |pkgcmd -u| while webapp runs * changing watch face Bug: http://suprem.sec.samsung.net/jira/browse/TWF-2765 Change-Id: I1767ef5f14e393ffc59668b0b9925d781abfd2f5 Signed-off-by: Youngsoo Choi --- diff --git a/extensions/renderer/xwalk_extension_renderer_controller.cc b/extensions/renderer/xwalk_extension_renderer_controller.cc index 59e45b7..01c1ece 100755 --- a/extensions/renderer/xwalk_extension_renderer_controller.cc +++ b/extensions/renderer/xwalk_extension_renderer_controller.cc @@ -22,6 +22,9 @@ namespace extensions { +// static +int XWalkExtensionRendererController::plugin_session_count = 0; + namespace { void CreateExtensionModules(XWalkExtensionClient* client, @@ -81,12 +84,16 @@ void XWalkExtensionRendererController::DidCreateScriptContext( CreateExtensionModules(extensions_client_.get(), module_system); module_system->Initialize(); + plugin_session_count++; + LOGGER(DEBUG) << "plugin_session_count : " << plugin_session_count; } void XWalkExtensionRendererController::WillReleaseScriptContext( v8::Handle context) { v8::Context::Scope contextScope(context); XWalkModuleSystem::ResetModuleSystemFromContext(context); + plugin_session_count--; + LOGGER(DEBUG) << "plugin_session_count : " << plugin_session_count; } void XWalkExtensionRendererController::OnReceivedIPCMessage( diff --git a/extensions/renderer/xwalk_extension_renderer_controller.h b/extensions/renderer/xwalk_extension_renderer_controller.h index 4927d21..95e3145 100755 --- a/extensions/renderer/xwalk_extension_renderer_controller.h +++ b/extensions/renderer/xwalk_extension_renderer_controller.h @@ -20,6 +20,7 @@ class XWalkExtensionClient; class XWalkExtensionRendererController { public: static XWalkExtensionRendererController& GetInstance(); + static int plugin_session_count; void DidCreateScriptContext(v8::Handle context); void WillReleaseScriptContext(v8::Handle context); diff --git a/runtime/browser/runtime_process.cc b/runtime/browser/runtime_process.cc index 859aa3a..83d7645 100755 --- a/runtime/browser/runtime_process.cc +++ b/runtime/browser/runtime_process.cc @@ -28,6 +28,7 @@ #include "common/command_line.h" #include "common/logger.h" #include "common/profiler.h" +#include "extensions/renderer/xwalk_extension_renderer_controller.h" #include "runtime/browser/runtime.h" #include "runtime/common/constants.h" #include "runtime/browser/prelauncher.h" @@ -35,6 +36,7 @@ #include "runtime/browser/ui_runtime.h" +using namespace extensions; bool g_prelaunch = false; #ifdef WATCH_FACE_FEATURE_SUPPORT @@ -132,16 +134,22 @@ int real_main(int argc, char* argv[]) { std::unique_ptr runtime = runtime::Runtime::MakeRuntime(appdata); ret = runtime->Exec(argc, argv); - if (runtime->is_on_terminate_called) { - LOGGER(INFO) << "Defer termination of main loop"; + if (ret) + LOGGER(ERROR) << "Exec returns non zero."; + LOGGER(DEBUG) << "plugin_session_count : " << + XWalkExtensionRendererController::plugin_session_count; + if (XWalkExtensionRendererController::plugin_session_count > 0) { + LOGGER(DEBUG) << "Defer termination of main loop"; ecore_main_loop_begin(); } runtime.reset(); } + LOGGER(DEBUG) << "ewk_shutdown"; ewk_shutdown(); elm_shutdown(); elm_exit(); + LOGGER(DEBUG) << "EXIT_SUCCESS"; return EXIT_SUCCESS; } diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index 9a5d50b..68143a8 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -37,6 +37,7 @@ #include "common/profiler.h" #include "common/resource_manager.h" #include "common/string_utils.h" +#include "extensions/renderer/xwalk_extension_renderer_controller.h" #include "runtime/browser/native_window.h" #include "runtime/browser/notification_manager.h" #include "runtime/browser/popup.h" @@ -51,6 +52,10 @@ #error INJECTED_BUNDLE_PATH is not set. #endif +#define TIMER_INTERVAL 0.1 + +using namespace extensions; + namespace runtime { namespace { @@ -222,8 +227,10 @@ static void InitializeNotificationCallback(Ewk_Context* ewk_context, static Eina_Bool ExitAppIdlerCallback(void* data) { WebApplication* app = static_cast(data); - if (app) + if (app) { + LOGGER(DEBUG) << "Terminate"; app->Terminate(); + } return ECORE_CALLBACK_CANCEL; } @@ -285,6 +292,7 @@ WebApplication::WebApplication( debug_mode_(false), verbose_mode_(false), lang_changed_mode_(false), + is_terminate_called_(false), ewk_context_( ewk_context_new_with_injected_bundle_path(INJECTED_BUNDLE_PATH)), has_ownership_of_ewk_context_(true), @@ -303,6 +311,7 @@ WebApplication::WebApplication( : launched_(false), debug_mode_(false), verbose_mode_(false), + is_terminate_called_(false), ewk_context_(context), has_ownership_of_ewk_context_(false), window_(window), @@ -637,23 +646,28 @@ void WebApplication::Suspend() { } void WebApplication::Terminate() { + is_terminate_called_ = true; if (terminator_) { + LOGGER(DEBUG) << "terminator_"; terminator_(); } else { + LOGGER(ERROR) << "There's no registered terminator."; elm_exit(); } auto extension_server = extensions::XWalkExtensionServer::GetInstance(); - LOGGER(INFO) << "Shutdown extension server"; + LOGGER(DEBUG) << "Shutdown extension server"; extension_server->Shutdown(); } void WebApplication::ClosePageFromOnTerminate() { + LOGGER(DEBUG); auto it = view_stack_.begin(); if (it != view_stack_.end()) { runtime::Runtime::is_on_terminate_called = true; for (; it != view_stack_.end(); ++it) { (*it)->ReplyToJavascriptDialog(); view_stack_.front()->SetVisibility(false); + LOGGER(DEBUG) << "ewk_view_page_close"; ewk_view_page_close((*it)->evas_object()); } } @@ -692,7 +706,13 @@ void WebApplication::RemoveWebViewFromStack(WebView* view) { } if (view_stack_.size() == 0) { - Terminate(); + // If |Terminate()| hasn't been called, + // main loop shouldn't be terminated here. + if (!is_terminate_called_) { + auto extension_server = XWalkExtensionServer::GetInstance(); + LOGGER(DEBUG) << "Shutdown extension server"; + extension_server->Shutdown(); + } } else if (current != view_stack_.front()) { view_stack_.front()->SetVisibility(true); window_->SetContent(view_stack_.front()->evas_object()); @@ -707,14 +727,43 @@ void WebApplication::RemoveWebViewFromStack(WebView* view) { view); } +Eina_Bool WebApplication::CheckPluginSession(void* user_data) +{ + WebApplication* that = static_cast(user_data); + if(XWalkExtensionRendererController::plugin_session_count > 0) { + LOGGER(ERROR) << "plugin_session_count : " << + XWalkExtensionRendererController::plugin_session_count; + return ECORE_CALLBACK_RENEW; + } + LOGGER(DEBUG) << "plugin_session_count : " << + XWalkExtensionRendererController::plugin_session_count; + LOGGER(DEBUG) << "Execute deferred termination of main loop"; + if (that->is_terminate_called_) { + ecore_main_loop_quit(); + } else { + if (that->terminator_) { + LOGGER(DEBUG) << "terminator_"; + that->terminator_(); + } else { + LOGGER(ERROR) << "There's no registered terminator."; + elm_exit(); + } + } + return ECORE_CALLBACK_CANCEL; +} + void WebApplication::OnClosedWebView(WebView* view) { + Ecore_Timer* timeout_id = NULL; // Reply to javascript dialog for preventing freeze issue. view->ReplyToJavascriptDialog(); RemoveWebViewFromStack(view); - if (runtime::Runtime::is_on_terminate_called) { - LOGGER(INFO) << "Execute deferred termination of main loop"; - ecore_main_loop_quit(); + LOGGER(DEBUG) << "plugin_session_count : " << + XWalkExtensionRendererController::plugin_session_count; + if (XWalkExtensionRendererController::plugin_session_count > 0) { + timeout_id = ecore_timer_add(TIMER_INTERVAL, CheckPluginSession, this); + if (!timeout_id) + LOGGER(ERROR) << "It's failed to create timer"; } } @@ -831,6 +880,7 @@ void WebApplication::OnHardwareKey(WebView* view, const std::string& keyname) { if(enabled) view->EvalJavascript(kBackKeyEventScript); if (!view->Backward()) { + LOGGER(DEBUG) << "Terminate"; Terminate(); } } @@ -846,6 +896,7 @@ void WebApplication::OnHardwareKey(WebView* view, const std::string& keyname) { (app_data_->widget_info() != NULL && app_data_->widget_info()->view_modes() == "windowed")) { if (!view->Backward()) { + LOGGER(DEBUG) << "Terminate"; Terminate(); } } diff --git a/runtime/browser/web_application.h b/runtime/browser/web_application.h index 751e809..48665e8 100755 --- a/runtime/browser/web_application.h +++ b/runtime/browser/web_application.h @@ -106,6 +106,7 @@ class WebApplication : public WebView::EventListener { #ifdef MANUAL_ROTATE_FEATURE_SUPPORT virtual void OnRotatePrepared(WebView* view); #endif // MANUAL_ROTATE_FEATURE_SUPPORT + static Eina_Bool CheckPluginSession(void* user_data); private: bool Initialize(); @@ -130,6 +131,7 @@ class WebApplication : public WebView::EventListener { bool debug_mode_; bool verbose_mode_; bool lang_changed_mode_; + bool is_terminate_called_; Ewk_Context* ewk_context_; bool has_ownership_of_ewk_context_; NativeWindow* window_;