[AT-SPI] Add NUIViewAccessible::Detach() 67/300567/1 accepted/tizen/7.0/unified/20231030.164723 accepted/tizen/7.0/unified/20231116.025858
authorArtur Świgoń <a.swigon@samsung.com>
Thu, 19 Oct 2023 15:59:58 +0000 (17:59 +0200)
committerArtur Świgoń <a.swigon@samsung.com>
Fri, 27 Oct 2023 07:47:02 +0000 (09:47 +0200)
The application may crash if the View is disposed but the Accessibility
infrastructure calls one of the View methods. Detaching the
NUIViewAccessible proxy object in View.Dispose() should prevent that.

Change-Id: I9a86fbda9b1ec6bdb40482195a1541b209b99fcc

dali-csharp-binder/src/nui-view-accessible.cpp
dali-csharp-binder/src/nui-view-accessible.h

index 8e69866..8aad34e 100644 (file)
@@ -137,6 +137,11 @@ void NUIViewAccessible::SetAccessibilityDelegate(const AccessibilityDelegate* ac
   mTable = accessibilityDelegate;
 }
 
+void NUIViewAccessible::Detach()
+{
+  mIsDetached = true;
+}
+
 std::string NUIViewAccessible::StealString(char* str)
 {
   std::string ret{};
@@ -167,6 +172,16 @@ T NUIViewAccessible::StealObject(T* obj)
 template<Interface I, typename R, typename... Args>
 R NUIViewAccessible::CallMethod(R (*method)(RefObject*, Args...), Args... args) const
 {
+  if(mIsDetached)
+  {
+    DALI_LOG_ERROR("Method called on detached NUIViewAccessible[%p]", static_cast<const void*>(this));
+
+    if constexpr(std::is_same_v<R, void>)
+      return;
+    else
+      return R{};
+  }
+
   DALI_ASSERT_DEBUG(method);
   DALI_ASSERT_ALWAYS(GetInterfaces()[I]);
 
@@ -718,6 +733,21 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Dali_Accessibility_SetAccessibilityDelegate(c
   }));
 }
 
+SWIGEXPORT void SWIGSTDCALL CSharp_Dali_Accessibility_DetachAccessibleObject(Dali::Toolkit::Control* arg1_control)
+{
+  GUARD_ON_NULL_RET(arg1_control);
+
+  try_catch(([&]() {
+    auto* actorAccessible = Dali::Accessibility::Accessible::Get(*arg1_control);
+    auto* viewAccessible  = dynamic_cast<NUIViewAccessible*>(actorAccessible);
+
+    if(viewAccessible)
+    {
+      viewAccessible->Detach();
+    }
+  }));
+}
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 332158a..dd506bb 100644 (file)
@@ -54,6 +54,8 @@ public:
 
   static void SetAccessibilityDelegate(const AccessibilityDelegate* accessibilityDelegate);
 
+  void Detach();
+
   // Standard interfaces (Accessible, Action, Component)
 
   std::string GetNameRaw() const override;
@@ -248,6 +250,9 @@ private:
    */
   template<Dali::Accessibility::AtspiInterface I, typename R, typename... Args>
   R CallMethod(R (*method)(Dali::RefObject*, Args...), Args... args) const;
+
+  // Prevents calling C# methods if the View has been disposed
+  bool mIsDetached = false;
 };
 
 #endif // NUI_VIEW_ACCESSIBLE_H