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 1d01b999a8af07e724b3b63d90d39d95b8abc34a..859aa3a6b0ce662ab064ac562c414bc7c0e5d670 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 856c8abcc51acb8018c07222def9765d8171783a..ab45d1b817d85141389259e036905157745918cb 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 1c31d210ea9673a85151e9e3461dff1040464d71..e72ad8de0fd51759265c8f4287921ba6b700199c 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_;