From 8b10d34491ddfcc7cf5fd3d75aa873e070c2ea7e Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Tue, 3 Jan 2017 13:10:51 +0900 Subject: [PATCH 01/16] Reply to javascript dialog when exiting by command |pkgcmd| There's an issue not to kill web app when javascript dialog is opened even if the command |pkgcmd -k -n | is executed to kill the web app. To prevent the issue, this CL replies to the dialog to close it right before the termination. Bug: TSAM-11809, TSAM-11813 Url: http://suprem.sec.samsung.net/jira/browse/TSAM-11809 Url: http://suprem.sec.samsung.net/jira/browse/TSAM-11813 Change-Id: I4757f45b3731d25cb57876f12c7b2e52b9f62af7 Signed-off-by: Youngsoo Choi --- runtime/browser/web_application.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index 753711a..856c8ab 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -660,6 +660,7 @@ void WebApplication::ClosePageFromOnTerminate() { 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); ewk_view_page_close((*it)->evas_object()); } -- 2.7.4 From 5b72df93ded5c2f5dcbb8a1135ae9bc1937e0760 Mon Sep 17 00:00:00 2001 From: Sanjana Venkatachalam Date: Fri, 30 Dec 2016 14:51:29 +0530 Subject: [PATCH 02/16] Check web app's view mode when exiting fullscreen [Issue#] PLM P161223-02573 [Problem] Indicator is visible when user exits fullscreen after watching a video in Hotstar web app even if viewmodes="fullscreen" is mentioned in config.xml [Cause] When exit fullscreen callback is received, indicator is shown even if viewmode of webapp is fullscreen [Solution] Indicator is not shown if viewmode of webapp is fullscreen [Verification] 1) Build and install crosswalk-tizen rpm 2) Launch Hotstar webapp and play any video 3) Open fullscreen mode and exit fullscreen 4) Indicator should not be visible Change-Id: Ic7452d3da8f7e53ef4768b3f8ed619504fbc208e --- runtime/browser/native_window.cc | 7 ++++++- runtime/browser/native_window.h | 2 ++ runtime/browser/web_application.cc | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/runtime/browser/native_window.cc b/runtime/browser/native_window.cc index 5712dff..9350c66 100755 --- a/runtime/browser/native_window.cc +++ b/runtime/browser/native_window.cc @@ -72,6 +72,7 @@ NativeWindow::NativeWindow() : window_(NULL), window_type_(Type::NORMAL), initialized_(false), + currentViewModeFullScreen_(false), focus_(NULL), content_(NULL), rotation_(0), @@ -271,6 +272,10 @@ void NativeWindow::SetAutoRotation() { rotation_ = elm_win_rotation_get(window_); } +void NativeWindow::SetCurrentViewModeFullScreen(bool mode) { + currentViewModeFullScreen_ = mode; +} + void NativeWindow::Show() { evas_object_show(window_); } @@ -285,7 +290,7 @@ void NativeWindow::InActive() { void NativeWindow::FullScreen(bool enable) { elm_win_indicator_opacity_set(window_, - enable ? ELM_WIN_INDICATOR_TRANSPARENT : ELM_WIN_INDICATOR_OPAQUE); + (enable || currentViewModeFullScreen_) ? ELM_WIN_INDICATOR_TRANSPARENT : ELM_WIN_INDICATOR_OPAQUE); } #ifdef MANUAL_ROTATE_FEATURE_SUPPORT diff --git a/runtime/browser/native_window.h b/runtime/browser/native_window.h index e939a01..7d23aa0 100755 --- a/runtime/browser/native_window.h +++ b/runtime/browser/native_window.h @@ -50,6 +50,7 @@ class NativeWindow { void SetRotationLock(int degree); void SetRotationLock(ScreenOrientation orientation); void SetAutoRotation(); + void SetCurrentViewModeFullScreen(bool mode); int AddRotationHandler(RotationHandler handler); void RemoveRotationHandler(int id); int rotation() const { return rotation_; } @@ -78,6 +79,7 @@ class NativeWindow { void DidFocusChanged(bool got); bool initialized_; + bool currentViewModeFullScreen_; Evas_Object* focus_; Evas_Object* content_; int rotation_; diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index 856c8ab..540b4e8 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -441,6 +441,7 @@ bool WebApplication::Initialize() { if (app_data_->widget_info() != NULL && app_data_->widget_info()->view_modes() == "fullscreen") { + window_->SetCurrentViewModeFullScreen(true); window_->FullScreen(true); } -- 2.7.4 From 193e6ee21adb9a80d4ef885c336ce2c54d5edc33 Mon Sep 17 00:00:00 2001 From: "jaekuk, lee" Date: Wed, 4 Jan 2017 11:13:00 +0900 Subject: [PATCH 03/16] Add a api of tizen version when creating new web view. Change-Id: Ica6df4f23e4a6637ae448e95080fcfb882add280 Signed-off-by: jaekuk, lee --- runtime/browser/web_application.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index 856c8ab..4d8fe2c 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -579,6 +579,7 @@ void WebApplication::AppControl( ClearViewStack(); WebView* view = view_stack_.front(); SetupWebView(view); + SetupWebViewTizenApplicationInfo(view); view->SetDefaultEncoding(res->encoding()); view->LoadUrl(res->uri(), res->mime()); window_->SetContent(view->evas_object()); @@ -672,6 +673,7 @@ void WebApplication::OnCreatedNewWebView(WebView* /*view*/, WebView* new_view) { view_stack_.front()->SetVisibility(false); SetupWebView(new_view); + SetupWebViewTizenApplicationInfo(new_view); view_stack_.push_front(new_view); window_->SetContent(new_view->evas_object()); } -- 2.7.4 From 345ed487fb09774323ab7d23fbbf6a5bb1eec7f8 Mon Sep 17 00:00:00 2001 From: "jaekuk, lee" Date: Wed, 4 Jan 2017 11:13:00 +0900 Subject: [PATCH 04/16] Add a api of tizen version when creating new web view and when receiving a event of appcontrol. Change-Id: Ica6df4f23e4a6637ae448e95080fcfb882add280 Signed-off-by: jaekuk, lee --- runtime/browser/web_application.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index 856c8ab..4d8fe2c 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -579,6 +579,7 @@ void WebApplication::AppControl( ClearViewStack(); WebView* view = view_stack_.front(); SetupWebView(view); + SetupWebViewTizenApplicationInfo(view); view->SetDefaultEncoding(res->encoding()); view->LoadUrl(res->uri(), res->mime()); window_->SetContent(view->evas_object()); @@ -672,6 +673,7 @@ void WebApplication::OnCreatedNewWebView(WebView* /*view*/, WebView* new_view) { view_stack_.front()->SetVisibility(false); SetupWebView(new_view); + SetupWebViewTizenApplicationInfo(new_view); view_stack_.push_front(new_view); window_->SetContent(new_view->evas_object()); } -- 2.7.4 From 20e92af566b0a619411521620a978069f7ac8543 Mon Sep 17 00:00:00 2001 From: "jaekuk, lee" Date: Thu, 5 Jan 2017 12:32:33 +0900 Subject: [PATCH 05/16] Modify prefix and suffix checking the allowed domain Change-Id: I960af6fd8254fcf071516f43f53f9650f0c357b2 Signed-off-by: jaekuk, lee --- common/resource_manager.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100644 => 100755 common/resource_manager.cc diff --git a/common/resource_manager.cc b/common/resource_manager.cc old mode 100644 new mode 100755 index 203f454..8881428 --- a/common/resource_manager.cc +++ b/common/resource_manager.cc @@ -519,12 +519,12 @@ bool ResourceManager::CheckAllowNavigation(const std::string& url) { bool prefix_wild = false; bool suffix_wild = false; std::string a_domain = a_domain_info.domain(); - if (utils::StartsWith(a_domain, "*.")) { + if (utils::StartsWith(a_domain, "*")) { prefix_wild = true; // *.domain.com -> .domain.com a_domain = a_domain.substr(1); } - if (utils::EndsWith(a_domain, ".*")) { + if (utils::EndsWith(a_domain, "*")) { suffix_wild = true; // domain.* -> domain. a_domain = a_domain.substr(0, a_domain.length() - 1); -- 2.7.4 From cdda603905ece7c48b08917f083e5f83dc10bb16 Mon Sep 17 00:00:00 2001 From: Youngmin Yoo Date: Thu, 5 Jan 2017 12:58:18 +0900 Subject: [PATCH 06/16] Fix URI scheme parsing IP/Host on the internet ex) http://user:password@www.tizen.org:8080/market/Item?12345 url_ = http://user:password@www.tizen.org:8080/market/Item?12345 scheme_ = http domain_ = www.tizen.org user_ = user password_ = password Link : https://www.w3.org/Addressing/rfc1738.txt Bug : P161229-04063 Bug : http://suprem.sec.samsung.net/jira/browse/TWF-2753 Change-Id: I71fbc95c5b71cd36c370c3ed34fe6d8176cb21a7 Signed-off-by: Youngmin Yoo --- common/url.cc | 5 +++++ common/url.h | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/common/url.cc b/common/url.cc index adfbff1..898190c 100644 --- a/common/url.cc +++ b/common/url.cc @@ -109,9 +109,14 @@ void URLImpl::ExtractDomain() { size_t start_of_domain = scheme_.empty() ? 0 : scheme_.length() + kSchemeIdLen; size_t end_of_domain = url_.find_first_of('/', start_of_domain); + size_t at = url_.find_first_of('@', start_of_domain); + if (at < end_of_domain) { + start_of_domain = at + 1; + } domain_ = url_.substr(start_of_domain, end_of_domain == std::string::npos ? std::string::npos : end_of_domain - start_of_domain); + LOGGER(INFO) << "Extract Domain is " << domain_; } void URLImpl::ExtractDomainPort() { diff --git a/common/url.h b/common/url.h index 89ef348..222e738 100644 --- a/common/url.h +++ b/common/url.h @@ -38,12 +38,14 @@ class URLImpl; * => domain_, path_ * * If the url does not have specific data, an empty string will be stored - * in the corresponding variables. + * in the corresponding variables.(RFC 1738) * - * ex) http://user:password@www.google.co.kr:8080/market/Item?12345 - * url_ = http://user:password@www.google.co.kr:8080/market/Item?12345 + * ex) http://user:password@www.tizen.org:8080/market/Item?12345 + * url_ = http://user:password@www.tizen.org:8080/market/Item?12345 * scheme_ = http - * domain_ = user:password@www.google.co.kr + * user_ = user + * password_ = password + * domain_ = www.tizen.org * port_ = 8080 * path_ = /market/Item?12345 */ -- 2.7.4 From 7ba3ec0f4e4b83abf21ad2b9bf8fd46a65427383 Mon Sep 17 00:00:00 2001 From: "ws29.jung" Date: Thu, 5 Jan 2017 13:22:04 +0900 Subject: [PATCH 07/16] Fix Hardware Key action when popup is on This patch fix hardware key handling when popup is shown. Before this patch, hardware key handled in wrt before popup action is done when key is repidly tabbed. Now when popup is on, wrt will not trigger event. Bug: http://suprem.sec.samsung.net/jira/browse/TSAM-12331 Change-Id: I7b620e4f4349e8c54849ee9d24a66c0ccbe062f7 Signed-off-by: ws29.jung --- runtime/browser/web_view_impl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/browser/web_view_impl.cc b/runtime/browser/web_view_impl.cc index ca2a92c..cc52275 100644 --- a/runtime/browser/web_view_impl.cc +++ b/runtime/browser/web_view_impl.cc @@ -993,7 +993,7 @@ void WebViewImpl::OnKeyEvent(Eext_Callback_Type key_type) { return; } - if (listener_) { + if (listener_ && !internal_popup_opened_) { listener_->OnHardwareKey(view_, keyname); } } -- 2.7.4 From a3b39d11bcfdb312ccbfde756457a9b1de87c946 Mon Sep 17 00:00:00 2001 From: "jaekuk, lee" Date: Thu, 5 Jan 2017 12:32:33 +0900 Subject: [PATCH 08/16] Modify prefix and suffix checking the allowed domain [P161229-05961]login page runs in browser Change-Id: I960af6fd8254fcf071516f43f53f9650f0c357b2 Signed-off-by: jaekuk, lee --- common/resource_manager.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100644 => 100755 common/resource_manager.cc diff --git a/common/resource_manager.cc b/common/resource_manager.cc old mode 100644 new mode 100755 index 203f454..8881428 --- a/common/resource_manager.cc +++ b/common/resource_manager.cc @@ -519,12 +519,12 @@ bool ResourceManager::CheckAllowNavigation(const std::string& url) { bool prefix_wild = false; bool suffix_wild = false; std::string a_domain = a_domain_info.domain(); - if (utils::StartsWith(a_domain, "*.")) { + if (utils::StartsWith(a_domain, "*")) { prefix_wild = true; // *.domain.com -> .domain.com a_domain = a_domain.substr(1); } - if (utils::EndsWith(a_domain, ".*")) { + if (utils::EndsWith(a_domain, "*")) { suffix_wild = true; // domain.* -> domain. a_domain = a_domain.substr(0, a_domain.length() - 1); -- 2.7.4 From 4bd9dac4a614ade1d3f3171cba62a67b73341ea8 Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Wed, 4 Jan 2017 18:01:10 +0900 Subject: [PATCH 09/16] Refactor for unifying fragmented termination sequences There have been fragmented termination sequences of following exit scenarios. * h/w back key * exit pop up menu * exit command |pkgcmd -k| * uninstall command |pkgcmd -u| while webapp runs This CL makes those termination sequences go through a extended main loop. Also, removing view stacks is only handled from closing window callback and then the extended main loop quits to terminate webapp. The extneded main loop provides enough time for termination of renderer thread and prevents dead lock. Bug: http://suprem.sec.samsung.net/jira/browse/TWF-2765 Change-Id: I0f6e8092bd092c07a841c6cab20be22c67fe4928 Signed-off-by: Youngsoo Choi --- runtime/browser/runtime_process.cc | 1 + runtime/browser/web_application.cc | 47 +++++++++++--------------------------- runtime/browser/web_application.h | 1 - 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/runtime/browser/runtime_process.cc b/runtime/browser/runtime_process.cc index 1d01b99..859aa3a 100755 --- a/runtime/browser/runtime_process.cc +++ b/runtime/browser/runtime_process.cc @@ -133,6 +133,7 @@ int real_main(int argc, char* argv[]) { runtime::Runtime::MakeRuntime(appdata); ret = runtime->Exec(argc, argv); if (runtime->is_on_terminate_called) { + LOGGER(INFO) << "Defer termination of main loop"; ecore_main_loop_begin(); } runtime.reset(); diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index 856c8ab..ab45d1b 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -222,16 +222,8 @@ static void InitializeNotificationCallback(Ewk_Context* ewk_context, static Eina_Bool ExitAppIdlerCallback(void* data) { WebApplication* app = static_cast(data); - if (app) { - std::list vstack = app->view_stack(); - auto it = vstack.begin(); - - for (; it != vstack.end(); ++it) { - vstack.front()->SetVisibility(false); - (*it)->Suspend(); - ewk_view_page_close((*it)->evas_object()); - } - } + if (app) + app->Terminate(); return ECORE_CALLBACK_CANCEL; } @@ -296,7 +288,6 @@ WebApplication::WebApplication( ewk_context_( ewk_context_new_with_injected_bundle_path(INJECTED_BUNDLE_PATH)), has_ownership_of_ewk_context_(true), - is_terminated_by_callback_(false), window_(window), appid_(app_data->app_id()), app_data_(app_data), @@ -314,7 +305,6 @@ WebApplication::WebApplication( verbose_mode_(false), ewk_context_(context), has_ownership_of_ewk_context_(false), - is_terminated_by_callback_(false), window_(window), appid_(app_data->app_id()), app_data_(app_data), @@ -645,13 +635,13 @@ void WebApplication::Suspend() { } void WebApplication::Terminate() { - is_terminated_by_callback_ = false; if (terminator_) { terminator_(); } else { elm_exit(); } auto extension_server = extensions::XWalkExtensionServer::GetInstance(); + LOGGER(INFO) << "Shutdown extension server"; extension_server->Shutdown(); } @@ -677,13 +667,8 @@ void WebApplication::OnCreatedNewWebView(WebView* /*view*/, WebView* new_view) { } void WebApplication::RemoveWebViewFromStack(WebView* view) { - if (view_stack_.size() == 0) { - if (is_terminated_by_callback_) { - Terminate(); - } else { - return; - } - } + if (view_stack_.size() == 0) + return; WebView* current = view_stack_.front(); if (current == view) { @@ -696,17 +681,11 @@ void WebApplication::RemoveWebViewFromStack(WebView* view) { } if (view_stack_.size() == 0) { - if (is_terminated_by_callback_) { - // In order to prevent the crash issue due to the callback - // which occur after destroying WebApplication class, - // we have to set the 'SetEventListener' to NULL. - view->SetEventListener(NULL); - Terminate(); - } else { - view->Suspend(); - ewk_view_page_close(view->evas_object()); - return; - } + // In order to prevent the crash issue due to the callback + // which occur after destroying WebApplication class, + // we have to set the 'SetEventListener' to NULL. + view->SetEventListener(NULL); + Terminate(); } else if (current != view_stack_.front()) { view_stack_.front()->SetVisibility(true); window_->SetContent(view_stack_.front()->evas_object()); @@ -722,12 +701,12 @@ void WebApplication::RemoveWebViewFromStack(WebView* view) { } void WebApplication::OnClosedWebView(WebView* view) { - is_terminated_by_callback_ = true; // 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(); } } @@ -845,7 +824,7 @@ void WebApplication::OnHardwareKey(WebView* view, const std::string& keyname) { if(enabled) view->EvalJavascript(kBackKeyEventScript); if (!view->Backward()) { - RemoveWebViewFromStack(view_stack_.front()); + Terminate(); } } return; @@ -860,7 +839,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()) { - RemoveWebViewFromStack(view_stack_.front()); + Terminate(); } } } else if (enabled && kKeyNameMenu == keyname) { diff --git a/runtime/browser/web_application.h b/runtime/browser/web_application.h index 1c31d21..e72ad8d 100755 --- a/runtime/browser/web_application.h +++ b/runtime/browser/web_application.h @@ -132,7 +132,6 @@ class WebApplication : public WebView::EventListener { bool lang_changed_mode_; Ewk_Context* ewk_context_; bool has_ownership_of_ewk_context_; - bool is_terminated_by_callback_; NativeWindow* window_; std::string appid_; std::string app_data_path_; -- 2.7.4 From a81a7aea7bdecbcb1d6b5c92376a032450f6782a Mon Sep 17 00:00:00 2001 From: "ws29.jung" Date: Mon, 9 Jan 2017 14:25:07 +0900 Subject: [PATCH 10/16] Disable autotextsizing with 2.4 compatible app When app is launching, wrt check compatibiliy then disable autotextsizing setting with 2.4 compatibl webapp This patch is made to resolve different app appearance issue between 2.4 and 3.0. Bug: P161227-02523 Change-Id: Ib358d7aa0241a4fd462d362ce9a4f80f3477d4e9 Signed-off-by: ws29.jung --- runtime/browser/web_application.cc | 11 ++++++----- runtime/browser/web_application.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index d40f95a..31613dd 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -486,7 +486,7 @@ void WebApplication::Launch(std::unique_ptr appcontrol) { // Setup View WebView* view = new WebView(window_, ewk_context_); SetupWebView(view); - SetupWebViewTizenApplicationInfo(view); + SetupWebViewCompatibilitySettings(view); std::unique_ptr res = resource_manager_->GetStartResource(appcontrol.get()); @@ -570,7 +570,7 @@ void WebApplication::AppControl( ClearViewStack(); WebView* view = view_stack_.front(); SetupWebView(view); - SetupWebViewTizenApplicationInfo(view); + SetupWebViewCompatibilitySettings(view); view->SetDefaultEncoding(res->encoding()); view->LoadUrl(res->uri(), res->mime()); window_->SetContent(view->evas_object()); @@ -664,7 +664,7 @@ void WebApplication::OnCreatedNewWebView(WebView* /*view*/, WebView* new_view) { view_stack_.front()->SetVisibility(false); SetupWebView(new_view); - SetupWebViewTizenApplicationInfo(new_view); + SetupWebViewCompatibilitySettings(new_view); view_stack_.push_front(new_view); window_->SetContent(new_view->evas_object()); } @@ -1047,14 +1047,15 @@ void WebApplication::SetupWebView(WebView* view) { } } -void WebApplication::SetupWebViewTizenApplicationInfo(WebView* view) { +void WebApplication::SetupWebViewCompatibilitySettings(WebView* view) { if (tizenWebKitCompatibilityEnabled()) { Ewk_Settings* settings = ewk_view_settings_get(view->evas_object()); ewk_settings_tizen_compatibility_mode_set(settings, m_tizenCompatibilitySettings.m_major, m_tizenCompatibilitySettings.m_minor, m_tizenCompatibilitySettings.m_release); - } + ewk_settings_text_autosizing_enabled_set(settings, EINA_FALSE); + } } bool WebApplication::OnDidNavigation(WebView* /*view*/, diff --git a/runtime/browser/web_application.h b/runtime/browser/web_application.h index e72ad8d..751e809 100755 --- a/runtime/browser/web_application.h +++ b/runtime/browser/web_application.h @@ -114,7 +114,7 @@ class WebApplication : public WebView::EventListener { void SendAppControlEvent(); void LaunchInspector(common::AppControl* appcontrol); void SetupWebView(WebView* view); - void SetupWebViewTizenApplicationInfo(WebView* view); + void SetupWebViewCompatibilitySettings(WebView* view); void RemoveWebViewFromStack(WebView* view); void SetupTizenVersion(); -- 2.7.4 From 88e577caa2f01c84b3ff6f7a5643aaeb7b3a3435 Mon Sep 17 00:00:00 2001 From: "ws29.jung" Date: Mon, 9 Jan 2017 21:23:32 +0900 Subject: [PATCH 11/16] Prevent duplicated eventcallback call Unexpectly, there is some case which calls same function twice. To prevent these case, it is proper to set eventlistener to NULL when webview is pop/erased from view stack. Bug: http://suprem.sec.samsung.net/jira/browse/TSAM-12508 Change-Id: Ie1931bc9d20e3db0c3dde04f640b82e8b3fa17dc Signed-off-by: ws29.jung --- runtime/browser/web_application.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index 31613dd..9a5d50b 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -675,19 +675,23 @@ void WebApplication::RemoveWebViewFromStack(WebView* view) { WebView* current = view_stack_.front(); if (current == view) { + // In order to prevent the crash issue due to the callback + // which occur after destroying WebApplication class, + // we have to set the 'SetEventListener' to NULL. + view->SetEventListener(NULL); view_stack_.pop_front(); } else { auto found = std::find(view_stack_.begin(), view_stack_.end(), view); if (found != view_stack_.end()) { + // In order to prevent the crash issue due to the callback + // which occur after destroying WebApplication class, + // we have to set the 'SetEventListener' to NULL. + view->SetEventListener(NULL); view_stack_.erase(found); } } if (view_stack_.size() == 0) { - // In order to prevent the crash issue due to the callback - // which occur after destroying WebApplication class, - // we have to set the 'SetEventListener' to NULL. - view->SetEventListener(NULL); Terminate(); } else if (current != view_stack_.front()) { view_stack_.front()->SetVisibility(true); -- 2.7.4 From ccb5936a271fc9502fb3ba8b82373fa92d99df80 Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Wed, 4 Jan 2017 18:01:10 +0900 Subject: [PATCH 12/16] 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 --- .../xwalk_extension_renderer_controller.cc | 7 +++ .../renderer/xwalk_extension_renderer_controller.h | 1 + runtime/browser/runtime_process.cc | 12 ++++- runtime/browser/web_application.cc | 63 +++++++++++++++++++--- runtime/browser/web_application.h | 2 + 5 files changed, 77 insertions(+), 8 deletions(-) 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_; -- 2.7.4 From a3069e4415e651b93ca597d2503c4792b16f9194 Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Tue, 10 Jan 2017 14:52:26 +0900 Subject: [PATCH 13/16] Remove unused varialbe is_on_terminate_called Since the termination sequence was unified using context session, the variable is_on_terminate_called hasn't been used. Bug: http://suprem.sec.samsung.net/jira/browse/TWF-2769 Change-Id: Ie30e501d1c9ed1934c9cea560922c69efe79b810 Signed-off-by: Youngsoo Choi --- runtime/browser/runtime.cc | 2 -- runtime/browser/runtime.h | 1 - runtime/browser/web_application.cc | 1 - 3 files changed, 4 deletions(-) diff --git a/runtime/browser/runtime.cc b/runtime/browser/runtime.cc index bba1168..4298837 100644 --- a/runtime/browser/runtime.cc +++ b/runtime/browser/runtime.cc @@ -32,8 +32,6 @@ namespace runtime { -bool Runtime::is_on_terminate_called = false; - Runtime::~Runtime() { } diff --git a/runtime/browser/runtime.h b/runtime/browser/runtime.h index b4f1029..00dea07 100755 --- a/runtime/browser/runtime.h +++ b/runtime/browser/runtime.h @@ -32,7 +32,6 @@ class Runtime { virtual int Exec(int argc, char* argv[]) = 0; - static bool is_on_terminate_called; static std::unique_ptr MakeRuntime( common::ApplicationData* app_data); diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index 68143a8..e0ef6a5 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -663,7 +663,6 @@ 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); -- 2.7.4 From aca556ce936f3967e8dcc017b0d9279951897d18 Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Thu, 12 Jan 2017 14:52:13 +0900 Subject: [PATCH 14/16] Locate ewk_view_page_close in extended main loop Sometimes, closing page callbkack is missing when the callback comes between terminating main loop and creating extended main loop. In that case, deadlock situation happens. To avoid the issue, the ewk_view_page_close needs to be called in extended main loop to assure receiving the callback. Also, evas object needs to be deleted when it's valid. Bug: http://suprem.sec.samsung.net/jira/browse/TWF-2782 Change-Id: I7a86121bc7c78225b54bb6fe22b934f62615a46d Signed-off-by: Youngsoo Choi --- runtime/browser/ime_runtime.cc | 5 ++++- runtime/browser/ime_runtime.h | 1 + runtime/browser/runtime.cc | 25 ++++++++++++++++++++++--- runtime/browser/runtime.h | 11 ++++++++++- runtime/browser/runtime_process.cc | 11 ++--------- runtime/browser/ui_runtime.cc | 6 +++++- runtime/browser/ui_runtime.h | 1 + runtime/browser/watch_runtime.cc | 5 ++++- runtime/browser/watch_runtime.h | 1 + runtime/browser/web_application.cc | 31 +++++++++++++++++++++++-------- runtime/browser/web_application.h | 2 +- runtime/browser/web_view_impl.cc | 1 + 12 files changed, 75 insertions(+), 25 deletions(-) diff --git a/runtime/browser/ime_runtime.cc b/runtime/browser/ime_runtime.cc index 0527c83..78a890a 100644 --- a/runtime/browser/ime_runtime.cc +++ b/runtime/browser/ime_runtime.cc @@ -163,8 +163,11 @@ void ImeRuntime::OnCreate() { } void ImeRuntime::OnTerminate() { +} + +void ImeRuntime::Terminate() { LOGGER(DEBUG) << "ime_app_terminate"; - ClosePageFromOnTerminate(application_); + ProcessClosingPage(application_); } void ImeRuntime::OnShow(int context_id, ime_context_h context) { diff --git a/runtime/browser/ime_runtime.h b/runtime/browser/ime_runtime.h index 1284a3d..b020539 100644 --- a/runtime/browser/ime_runtime.h +++ b/runtime/browser/ime_runtime.h @@ -42,6 +42,7 @@ class ImeRuntime : public Runtime { virtual void OnHide(int context_id); virtual void OnAppControl(); + virtual void Terminate(); private: WebApplication* application_; NativeWindow* native_window_; diff --git a/runtime/browser/runtime.cc b/runtime/browser/runtime.cc index 4298837..5861b08 100644 --- a/runtime/browser/runtime.cc +++ b/runtime/browser/runtime.cc @@ -20,6 +20,7 @@ #include "common/application_data.h" #include "common/command_line.h" +#include "common/logger.h" #include "runtime/common/constants.h" #include "runtime/browser/runtime.h" #include "runtime/browser/ui_runtime.h" @@ -30,6 +31,8 @@ #include "runtime/browser/watch_runtime.h" #endif // WATCH_FACE_FEATURE_SUPPORT +#define MAIN_LOOP_INTERVAL 1 + namespace runtime { Runtime::~Runtime() { @@ -55,9 +58,25 @@ std::unique_ptr Runtime::MakeRuntime( } } -void Runtime::ClosePageFromOnTerminate(WebApplication* app) { - if (app) - app->ClosePageFromOnTerminate(); +// static +Eina_Bool Runtime::ClosePageInExtendedMainLoop(void* user_data) +{ + LOGGER(DEBUG); + struct Timer* main_loop = static_cast(user_data); + main_loop->application->ClosePage(); + return ECORE_CALLBACK_CANCEL; +} + +void Runtime::ProcessClosingPage(WebApplication* application) { + LOGGER(DEBUG); + if (application) { + struct Timer main_loop; + main_loop.application = application; + main_loop.timer = ecore_timer_add(MAIN_LOOP_INTERVAL, ClosePageInExtendedMainLoop, &main_loop); + LOGGER(DEBUG) << "Defer termination of main loop"; + ecore_main_loop_begin(); + ecore_timer_del(main_loop.timer); + } } } // namespace runtime diff --git a/runtime/browser/runtime.h b/runtime/browser/runtime.h index 00dea07..63ddc97 100755 --- a/runtime/browser/runtime.h +++ b/runtime/browser/runtime.h @@ -29,6 +29,7 @@ namespace runtime { class Runtime { public: virtual ~Runtime() = 0; + virtual void Terminate() = 0; virtual int Exec(int argc, char* argv[]) = 0; @@ -36,7 +37,15 @@ class Runtime { common::ApplicationData* app_data); protected: - void ClosePageFromOnTerminate(WebApplication* app); + void ProcessClosingPage(WebApplication* application); + + private: + static Eina_Bool ClosePageInExtendedMainLoop(void* user_data); + struct Timer + { + WebApplication* application; + Ecore_Timer* timer; + }; }; } // namespace runtime diff --git a/runtime/browser/runtime_process.cc b/runtime/browser/runtime_process.cc index 83d7645..757fdfa 100755 --- a/runtime/browser/runtime_process.cc +++ b/runtime/browser/runtime_process.cc @@ -128,20 +128,13 @@ int real_main(int argc, char* argv[]) { #endif // WATCH_FACE_FEATURE_SUPPORT } - int ret = 0; // Runtime's destructor should be called before ewk_shutdown() { std::unique_ptr runtime = runtime::Runtime::MakeRuntime(appdata); - ret = runtime->Exec(argc, argv); - if (ret) + if (runtime->Exec(argc, argv)) 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->Terminate(); runtime.reset(); } LOGGER(DEBUG) << "ewk_shutdown"; diff --git a/runtime/browser/ui_runtime.cc b/runtime/browser/ui_runtime.cc index 4e20943..41fa8d9 100755 --- a/runtime/browser/ui_runtime.cc +++ b/runtime/browser/ui_runtime.cc @@ -142,7 +142,11 @@ bool UiRuntime::OnCreate() { } void UiRuntime::OnTerminate() { - ClosePageFromOnTerminate(application_.get()); +} + +void UiRuntime::Terminate() { + LOGGER(DEBUG); + ProcessClosingPage(application_.get()); } void UiRuntime::OnPause() { diff --git a/runtime/browser/ui_runtime.h b/runtime/browser/ui_runtime.h index 7aff1f7..1625abd 100644 --- a/runtime/browser/ui_runtime.h +++ b/runtime/browser/ui_runtime.h @@ -44,6 +44,7 @@ class UiRuntime : public Runtime { virtual void OnAppControl(app_control_h app_control); virtual void OnLanguageChanged(const std::string& language); virtual void OnLowMemory(); + virtual void Terminate(); private: void ResetWebApplication(NativeWindow::Type windowType); diff --git a/runtime/browser/watch_runtime.cc b/runtime/browser/watch_runtime.cc index 657a7f1..f166e72 100644 --- a/runtime/browser/watch_runtime.cc +++ b/runtime/browser/watch_runtime.cc @@ -99,7 +99,10 @@ bool WatchRuntime::OnCreate() { } void WatchRuntime::OnTerminate() { - ClosePageFromOnTerminate(application_); +} + +void WatchRuntime::Terminate() { + ProcessClosingPage(application_); } void WatchRuntime::OnPause() { diff --git a/runtime/browser/watch_runtime.h b/runtime/browser/watch_runtime.h index 94c23d2..7fd5c3a 100644 --- a/runtime/browser/watch_runtime.h +++ b/runtime/browser/watch_runtime.h @@ -46,6 +46,7 @@ class WatchRuntime : public Runtime { virtual void OnAmbientTick(watch_time_h watch_time); virtual void OnAmbientChanged(bool ambient_mode); + virtual void Terminate(); private: WebApplication* application_; NativeWindow* native_window_; diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index e0ef6a5..e11d9e0 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -659,15 +659,33 @@ void WebApplication::Terminate() { extension_server->Shutdown(); } -void WebApplication::ClosePageFromOnTerminate() { +void WebApplication::ClosePage() { LOGGER(DEBUG); + int valid_evas_object_count = 0; auto it = view_stack_.begin(); if (it != view_stack_.end()) { 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()); + if (ewk_view_page_close((*it)->evas_object())) { + LOGGER(DEBUG) << "ewk_view_page_close returns true"; + valid_evas_object_count++; + } else { + LOGGER(DEBUG) << "ewk_view_page_close returns false"; + } + } + } + if (valid_evas_object_count == 0) { + if (is_terminate_called_) { + ecore_main_loop_quit(); + } else { + if (terminator_) { + LOGGER(DEBUG) << "terminator_"; + terminator_(); + } else { + LOGGER(ERROR) << "There's no registered terminator."; + elm_exit(); + } } } } @@ -759,11 +777,8 @@ void WebApplication::OnClosedWebView(WebView* view) { 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"; - } + if (!ecore_timer_add(TIMER_INTERVAL, CheckPluginSession, this)) + LOGGER(ERROR) << "It's failed to create timer"; } void WebApplication::OnReceivedWrtMessage(WebView* view, diff --git a/runtime/browser/web_application.h b/runtime/browser/web_application.h index 48665e8..3fdbdfe 100755 --- a/runtime/browser/web_application.h +++ b/runtime/browser/web_application.h @@ -52,7 +52,7 @@ class WebApplication : public WebView::EventListener { void Suspend(); void Terminate(); - void ClosePageFromOnTerminate(); + void ClosePage(); std::string data_path() const { return app_data_path_; } void set_terminator(std::function terminator) { terminator_ = terminator; diff --git a/runtime/browser/web_view_impl.cc b/runtime/browser/web_view_impl.cc index cc52275..162bca9 100644 --- a/runtime/browser/web_view_impl.cc +++ b/runtime/browser/web_view_impl.cc @@ -633,6 +633,7 @@ void WebViewImpl::InitWindowCreateCallback() { auto close_callback = [](void* user_data, Evas_Object*, void*) { + LOGGER(DEBUG) << "close_callback is called"; WebViewImpl* self = static_cast(user_data); if (!self->listener_) { return; -- 2.7.4 From 7805d199bbb9ce9065fb4f3a77180879c663f1e7 Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Tue, 17 Jan 2017 14:07:27 +0900 Subject: [PATCH 15/16] Add elementary APIs for running web app without wrt-loader The |elm_init| and |elm_config_cache_flush_enabled_set| are missing when launching web app without wrt-loader. bug: http://suprem.sec.samsung.net/jira/browse/TWF-2800 Change-Id: I5effca0e67561b9ed1e900e6d5b86087143dfc81 Signed-off-by: Youngsoo Choi --- runtime/browser/runtime_process.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/runtime/browser/runtime_process.cc b/runtime/browser/runtime_process.cc index 757fdfa..a085bbc 100755 --- a/runtime/browser/runtime_process.cc +++ b/runtime/browser/runtime_process.cc @@ -148,10 +148,12 @@ int real_main(int argc, char* argv[]) { __attribute__((visibility("default"))) int main(int argc, char* argv[]) { + elm_init(argc, argv); + elm_config_cache_flush_enabled_set(EINA_TRUE); + if (strcmp(argv[0], "/usr/bin/wrt-loader") == 0) { - elm_init(argc, argv); - elm_config_cache_flush_enabled_set(EINA_TRUE); auto preload = [argv](void) { + LOGGER(DEBUG) << "run with wrt-loader"; g_prelaunch = true; ewk_init(); char* chromium_arg_options[] = { @@ -172,6 +174,7 @@ int main(int argc, char* argv[]) { auto prelaunch = runtime::PreLauncher::Prelaunch; return prelaunch(argc, argv, preload, did_launch, real_main); } else { + LOGGER(DEBUG) << "run without wrt-loader"; return real_main(argc, argv); } } -- 2.7.4 From ef77d1d5e4c12b9a657da10cb4decb0b7d96349c Mon Sep 17 00:00:00 2001 From: Youngsoo Choi Date: Mon, 16 Jan 2017 12:51:12 +0900 Subject: [PATCH 16/16] Do not create extended main loop for termination by |Terminate| There are two types of termination sequences. The first one is terminated by |Terminate| and another one is terminated by |OnTerminate| triggered by application framework. In case of termination by |OnTerminate|, app f/w emits elm_shutdown that quits main loop so extended main loop is needed to finish termination sequence. Btw, in case of termination by |Terminate|, app f/w does not interrupt current main loop so it is stll alive and extended main loop is not needed. This CL introduces not to create extended main loop for the termination by |Terminate|. Bug: http://suprem.sec.samsung.net/jira/browse/TWF-2804 Change-Id: I15147c9d07ec768bdb7f8acf92e18886ec2c100d Signed-off-by: Youngsoo Choi --- runtime/browser/runtime.cc | 19 +------- runtime/browser/runtime.h | 8 ---- runtime/browser/web_application.cc | 96 ++++++++++++++++++++------------------ runtime/browser/web_application.h | 9 ++++ 4 files changed, 62 insertions(+), 70 deletions(-) diff --git a/runtime/browser/runtime.cc b/runtime/browser/runtime.cc index 5861b08..2254bfc 100644 --- a/runtime/browser/runtime.cc +++ b/runtime/browser/runtime.cc @@ -58,25 +58,10 @@ std::unique_ptr Runtime::MakeRuntime( } } -// static -Eina_Bool Runtime::ClosePageInExtendedMainLoop(void* user_data) -{ - LOGGER(DEBUG); - struct Timer* main_loop = static_cast(user_data); - main_loop->application->ClosePage(); - return ECORE_CALLBACK_CANCEL; -} - void Runtime::ProcessClosingPage(WebApplication* application) { LOGGER(DEBUG); - if (application) { - struct Timer main_loop; - main_loop.application = application; - main_loop.timer = ecore_timer_add(MAIN_LOOP_INTERVAL, ClosePageInExtendedMainLoop, &main_loop); - LOGGER(DEBUG) << "Defer termination of main loop"; - ecore_main_loop_begin(); - ecore_timer_del(main_loop.timer); - } + if (application) + application->ProcessClosingPage(); } } // namespace runtime diff --git a/runtime/browser/runtime.h b/runtime/browser/runtime.h index 63ddc97..a003dac 100755 --- a/runtime/browser/runtime.h +++ b/runtime/browser/runtime.h @@ -38,14 +38,6 @@ class Runtime { protected: void ProcessClosingPage(WebApplication* application); - - private: - static Eina_Bool ClosePageInExtendedMainLoop(void* user_data); - struct Timer - { - WebApplication* application; - Ecore_Timer* timer; - }; }; } // namespace runtime diff --git a/runtime/browser/web_application.cc b/runtime/browser/web_application.cc index e11d9e0..97d9bb3 100755 --- a/runtime/browser/web_application.cc +++ b/runtime/browser/web_application.cc @@ -52,7 +52,8 @@ #error INJECTED_BUNDLE_PATH is not set. #endif -#define TIMER_INTERVAL 0.1 +#define SESSION_COUNTER_INTERVAL 0.1 +#define MAIN_LOOP_INTERVAL 1 using namespace extensions; @@ -647,20 +648,35 @@ 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(DEBUG) << "Shutdown extension server"; - extension_server->Shutdown(); + ClosePage(); +} + +// static +Eina_Bool WebApplication::ClosePageInExtendedMainLoop(void* user_data) +{ + LOGGER(DEBUG); + struct Timer* main_loop = static_cast(user_data); + main_loop->application->ClosePage(); + return ECORE_CALLBACK_CANCEL; +} + +void WebApplication::ProcessClosingPage() { + LOGGER(DEBUG); + + main_loop.application = this; + main_loop.timer = ecore_timer_add(MAIN_LOOP_INTERVAL, + ClosePageInExtendedMainLoop, &main_loop); + if (!main_loop.timer) + LOGGER(ERROR) << "It's failed to create main_loop timer"; + LOGGER(DEBUG) << "Defer termination of main loop"; + ecore_main_loop_begin(); + ecore_timer_del(main_loop.timer); + ecore_timer_del(session_counter.timer); } void WebApplication::ClosePage() { LOGGER(DEBUG); + int valid_evas_object_count = 0; auto it = view_stack_.begin(); if (it != view_stack_.end()) { @@ -675,18 +691,20 @@ void WebApplication::ClosePage() { } } } - if (valid_evas_object_count == 0) { - if (is_terminate_called_) { - ecore_main_loop_quit(); - } else { - if (terminator_) { - LOGGER(DEBUG) << "terminator_"; - terminator_(); - } else { - LOGGER(ERROR) << "There's no registered terminator."; - elm_exit(); - } - } + if (valid_evas_object_count == 0) + Exit(); +} + +void WebApplication::Exit() { + if (!is_terminate_called_) + ecore_main_loop_quit(); + + if (terminator_) { + LOGGER(DEBUG) << "terminator_"; + terminator_(); + } else { + LOGGER(ERROR) << "There's no registered terminator."; + elm_exit(); } } @@ -723,13 +741,9 @@ void WebApplication::RemoveWebViewFromStack(WebView* view) { } if (view_stack_.size() == 0) { - // 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(); - } + 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()); @@ -746,7 +760,7 @@ void WebApplication::RemoveWebViewFromStack(WebView* view) { Eina_Bool WebApplication::CheckPluginSession(void* user_data) { - WebApplication* that = static_cast(user_data); + struct Timer* session_counter = static_cast(user_data); if(XWalkExtensionRendererController::plugin_session_count > 0) { LOGGER(ERROR) << "plugin_session_count : " << XWalkExtensionRendererController::plugin_session_count; @@ -755,30 +769,22 @@ Eina_Bool WebApplication::CheckPluginSession(void* user_data) 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(); - } - } + session_counter->application->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); LOGGER(DEBUG) << "plugin_session_count : " << XWalkExtensionRendererController::plugin_session_count; - if (!ecore_timer_add(TIMER_INTERVAL, CheckPluginSession, this)) - LOGGER(ERROR) << "It's failed to create timer"; + session_counter.application = this; + session_counter.timer = ecore_timer_add(SESSION_COUNTER_INTERVAL, + CheckPluginSession, &session_counter); + if (!session_counter.timer) + LOGGER(ERROR) << "It's failed to create session_counter timer"; } void WebApplication::OnReceivedWrtMessage(WebView* view, diff --git a/runtime/browser/web_application.h b/runtime/browser/web_application.h index 3fdbdfe..446fb49 100755 --- a/runtime/browser/web_application.h +++ b/runtime/browser/web_application.h @@ -53,6 +53,9 @@ class WebApplication : public WebView::EventListener { void Terminate(); void ClosePage(); + void Exit(); + void ProcessClosingPage(); + std::string data_path() const { return app_data_path_; } void set_terminator(std::function terminator) { terminator_ = terminator; @@ -107,6 +110,12 @@ class WebApplication : public WebView::EventListener { virtual void OnRotatePrepared(WebView* view); #endif // MANUAL_ROTATE_FEATURE_SUPPORT static Eina_Bool CheckPluginSession(void* user_data); + static Eina_Bool ClosePageInExtendedMainLoop(void* user_data); + struct Timer + { + WebApplication* application; + Ecore_Timer* timer; + } main_loop, session_counter; private: bool Initialize(); -- 2.7.4