[Tizen][Web] Update WebView terminate crash 26/283926/1
authorEunki, Hong <eunkiki.hong@samsung.com>
Mon, 7 Nov 2022 08:43:26 +0000 (17:43 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Mon, 7 Nov 2022 08:50:45 +0000 (17:50 +0900)
Due to tizen_7.0 branch will not merge devel/master,
we should sync latest code style by our hands.

== This git commit is squash of below two patches ==

Revert "[Tizen][Web] Fix WebView terminate crash"

This reverts commit 52e86addc31a0b4393e8b7450e4b3c8a877f633d.

[Web] Fix WebView terminate crash

Due to the web context closed before all webview released,
mPlugin and mDestroyWebEnginePtr are invalid.

This patch make reference count so we can assume that
plugin is alive

Change-Id: Ia4a7f810c7aa02c3bd93c061ddb876debd6d4ad5

dali/internal/web-engine/common/web-engine-impl.cpp

index c530481..3d5e300 100644 (file)
@@ -26,7 +26,6 @@
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/environment-variable.h>
-#include <dali/devel-api/adaptor-framework/lifecycle-controller.h>
 #include <dali/devel-api/adaptor-framework/web-engine/web-engine-back-forward-list.h>
 #include <dali/devel-api/adaptor-framework/web-engine/web-engine-certificate.h>
 #include <dali/devel-api/adaptor-framework/web-engine/web-engine-console-message.h>
@@ -69,37 +68,83 @@ Dali::TypeRegistration type(typeid(Dali::WebEngine), typeid(Dali::BaseHandle), C
 
 /**
  * @brief Control the WebEnginePlugin library lifecycle.
+ * Hold the plugin library handle in static singletone.
+ * It will makes library handle alives during all WebEngine resources create & destory.
  */
 struct WebEnginePluginObject
 {
 public:
-  WebEnginePluginObject()
-  : mPluginName{},
-    mHandle{nullptr},
-    mCreateWebEnginePtr{nullptr},
-    mDestroyWebEnginePtr{nullptr},
-    mGetWebEngineContextPtr{nullptr},
-    mGetWebEngineCookieManagerPtr{nullptr}
+  static WebEnginePluginObject& GetInstance()
   {
+    static WebEnginePluginObject gPluginHandle;
+    return gPluginHandle;
   }
 
-  ~WebEnginePluginObject()
+  /**
+   * @brief Converts an handle to a bool.
+   *
+   * This is useful for checking whether the WebEnginePluginObject succes to load library.
+   * @note We don't check mHandle because it is possible that mHandle load is success but
+   * Create/Destroy API load failed.
+   */
+  explicit operator bool() const
   {
-    if(mHandle)
+    return mLoadSuccess;
+  }
+
+  bool InitializeContextHandle()
+  {
+    if(!mHandle)
     {
-      dlclose(mHandle);
-      mHandle = nullptr;
+      return false;
+    }
+
+    if(!mGetWebEngineContextPtr)
+    {
+      mGetWebEngineContextPtr = reinterpret_cast<GetWebEngineContext>(dlsym(mHandle, "GetWebEngineContext"));
+
+      if(!mGetWebEngineContextPtr)
+      {
+        DALI_LOG_ERROR("Can't load symbol GetWebEngineContext(), error: %s\n", dlerror());
+        return false;
+      }
     }
+
+    return true;
   }
 
-  bool InitializePluginHandle()
+  bool InitializeCookieManagerHandle()
   {
-    if(mHandle)
+    if(!mHandle)
     {
-      DALI_LOG_ERROR("Plugin.so has been opened already.\n");
-      return true;
+      return false;
     }
 
+    if(!mGetWebEngineCookieManagerPtr)
+    {
+      mGetWebEngineCookieManagerPtr = reinterpret_cast<GetWebEngineCookieManager>(dlsym(mHandle, "GetWebEngineCookieManager"));
+
+      if(!mGetWebEngineCookieManagerPtr)
+      {
+        DALI_LOG_ERROR("Can't load symbol GetWebEngineCookieManager(), error: %s\n", dlerror());
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+private:
+  // Private constructor / destructor
+  WebEnginePluginObject()
+  : mPluginName{},
+    mLoadSuccess{false},
+    mHandle{nullptr},
+    mCreateWebEnginePtr{nullptr},
+    mDestroyWebEnginePtr{nullptr},
+    mGetWebEngineContextPtr{nullptr},
+    mGetWebEngineCookieManagerPtr{nullptr}
+  {
     if(mPluginName.length() == 0)
     {
       // mPluginName is not initialized yet.
@@ -118,64 +163,36 @@ public:
     if(!mHandle)
     {
       DALI_LOG_ERROR("Can't load %s : %s\n", mPluginName.c_str(), dlerror());
-      return false;
+      return;
     }
 
     mCreateWebEnginePtr = reinterpret_cast<CreateWebEngineFunction>(dlsym(mHandle, "CreateWebEnginePlugin"));
     if(mCreateWebEnginePtr == nullptr)
     {
       DALI_LOG_ERROR("Can't load symbol CreateWebEnginePlugin(), error: %s\n", dlerror());
-
-      return false;
+      return;
     }
 
     mDestroyWebEnginePtr = reinterpret_cast<DestroyWebEngineFunction>(dlsym(mHandle, "DestroyWebEnginePlugin"));
     if(mDestroyWebEnginePtr == nullptr)
     {
       DALI_LOG_ERROR("Can't load symbol DestroyWebEnginePlugin(), error: %s\n", dlerror());
-      return false;
-    }
-
-    return true;
-  }
-
-  bool InitializeContextHandle()
-  {
-    if(!InitializePluginHandle())
-    {
-      return false;
-    }
-
-    mGetWebEngineContextPtr = reinterpret_cast<GetWebEngineContext>(dlsym(mHandle, "GetWebEngineContext"));
-
-    if(!mGetWebEngineContextPtr)
-    {
-      DALI_LOG_ERROR("Can't load symbol GetWebEngineContext(), error: %s\n", dlerror());
-      return false;
+      return;
     }
 
-    return true;
+    mLoadSuccess = true;
   }
 
-  bool InitializeCookieManagerHandle()
+  ~WebEnginePluginObject()
   {
-    if(!InitializePluginHandle())
-    {
-      return false;
-    }
-
-    mGetWebEngineCookieManagerPtr = reinterpret_cast<GetWebEngineCookieManager>(dlsym(mHandle, "GetWebEngineCookieManager"));
-
-    if(!mGetWebEngineCookieManagerPtr)
+    if(mHandle)
     {
-      DALI_LOG_ERROR("Can't load symbol GetWebEngineCookieManager(), error: %s\n", dlerror());
-      return false;
+      dlclose(mHandle);
+      mHandle      = nullptr;
+      mLoadSuccess = false;
     }
-
-    return true;
   }
 
-private:
   WebEnginePluginObject(const WebEnginePluginObject&) = delete;
   WebEnginePluginObject(WebEnginePluginObject&&)      = delete;
   WebEnginePluginObject& operator=(const WebEnginePluginObject&) = delete;
@@ -186,6 +203,8 @@ private:
                            /// Note: Dali WebView policy does not allow to use multiple web engines in an application.
                            /// So once pluginName is set to non-empty string, it will not change.
 
+  bool mLoadSuccess; ///< True if library loaded successfully. False otherwise.
+
 public:
   using CreateWebEngineFunction  = Dali::WebEnginePlugin* (*)();
   using DestroyWebEngineFunction = void (*)(Dali::WebEnginePlugin* plugin);
@@ -201,8 +220,6 @@ public:
   GetWebEngineCookieManager mGetWebEngineCookieManagerPtr; ///< Function to get WebEngineCookieManager
 };
 
-static WebEnginePluginObject gPluginHandle; // Keep this object as static, so Let we assume that library closed after all WebEngines are disposed.
-
 } // unnamed namespace
 
 WebEnginePtr WebEngine::New()
@@ -219,14 +236,14 @@ WebEnginePtr WebEngine::New()
 
 Dali::WebEngineContext* WebEngine::GetContext()
 {
-  if(!gPluginHandle.InitializeContextHandle())
+  if(!WebEnginePluginObject::GetInstance().InitializeContextHandle())
   {
     return nullptr;
   }
 
-  if(gPluginHandle.mGetWebEngineContextPtr)
+  if(WebEnginePluginObject::GetInstance().mGetWebEngineContextPtr)
   {
-    return gPluginHandle.mGetWebEngineContextPtr();
+    return WebEnginePluginObject::GetInstance().mGetWebEngineContextPtr();
   }
 
   return nullptr;
@@ -234,14 +251,14 @@ Dali::WebEngineContext* WebEngine::GetContext()
 
 Dali::WebEngineCookieManager* WebEngine::GetCookieManager()
 {
-  if(!gPluginHandle.InitializeCookieManagerHandle())
+  if(!WebEnginePluginObject::GetInstance().InitializeCookieManagerHandle())
   {
     return nullptr;
   }
 
-  if(gPluginHandle.mGetWebEngineCookieManagerPtr)
+  if(WebEnginePluginObject::GetInstance().mGetWebEngineCookieManagerPtr)
   {
-    return gPluginHandle.mGetWebEngineCookieManagerPtr();
+    return WebEnginePluginObject::GetInstance().mGetWebEngineCookieManagerPtr();
   }
 
   return nullptr;
@@ -257,9 +274,10 @@ WebEngine::~WebEngine()
   if(mPlugin != nullptr)
   {
     mPlugin->Destroy();
-    if(gPluginHandle.mDestroyWebEnginePtr != nullptr)
+    // Check whether plugin load sccess or not.
+    if(DALI_LIKELY(WebEnginePluginObject::GetInstance()))
     {
-      gPluginHandle.mDestroyWebEnginePtr(mPlugin);
+      WebEnginePluginObject::GetInstance().mDestroyWebEnginePtr(mPlugin);
     }
     mPlugin = nullptr;
   }
@@ -267,12 +285,13 @@ WebEngine::~WebEngine()
 
 bool WebEngine::Initialize()
 {
-  if(!gPluginHandle.InitializePluginHandle())
+  // Check whether plugin load sccess or not.
+  if(!WebEnginePluginObject::GetInstance())
   {
     return false;
   }
 
-  mPlugin = gPluginHandle.mCreateWebEnginePtr();
+  mPlugin = WebEnginePluginObject::GetInstance().mCreateWebEnginePtr();
   if(mPlugin == nullptr)
   {
     DALI_LOG_ERROR("Can't create the WebEnginePlugin object\n");