Refactor for unifying fragmented termination sequences 37/108437/7
authorYoungsoo Choi <kenshin.choi@samsung.com>
Wed, 4 Jan 2017 09:01:10 +0000 (18:01 +0900)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Fri, 6 Jan 2017 00:58:46 +0000 (09:58 +0900)
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 <kenshin.choi@samsung.com>
runtime/browser/runtime_process.cc
runtime/browser/web_application.cc
runtime/browser/web_application.h

index 1d01b99..859aa3a 100755 (executable)
@@ -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();
index 856c8ab..ab45d1b 100755 (executable)
@@ -222,16 +222,8 @@ static void InitializeNotificationCallback(Ewk_Context* ewk_context,
 static Eina_Bool ExitAppIdlerCallback(void* data) {
   WebApplication* app = static_cast<WebApplication*>(data);
 
-  if (app) {
-    std::list<WebView*> 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) {
index 1c31d21..e72ad8d 100755 (executable)
@@ -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_;