libaurum: fix leaking memory by using smart pointer
authorWonki Kim <wonki_.kim@samsung.com>
Mon, 23 Mar 2020 08:43:52 +0000 (17:43 +0900)
committerWonki Kim <wonki_.kim@samsung.com>
Tue, 24 Mar 2020 09:05:52 +0000 (18:05 +0900)
Change-Id: I5881a568c4ed16234c19521392750b9b84b3b4ab

20 files changed:
libaurum/inc/AccessibleNode.h
libaurum/inc/AccessibleWatcher.h
libaurum/inc/Comparer.h
libaurum/inc/ISearchable.h
libaurum/inc/PartialMatch.h
libaurum/inc/Sel.h
libaurum/inc/UiDevice.h
libaurum/inc/UiObject.h
libaurum/inc/UiSelector.h
libaurum/inc/Until.h
libaurum/src/AccessibleNode.cc
libaurum/src/AccessibleWatcher.cc
libaurum/src/Comparer.cc
libaurum/src/PartialMatch.cc
libaurum/src/Sel.cc
libaurum/src/UiDevice.cc
libaurum/src/UiObject.cc
libaurum/src/UiSelector.cc
libaurum/src/Until.cc
tests/ua_test.cpp

index 89981ca..a9eddc1 100644 (file)
@@ -2,6 +2,8 @@
 #define ACCESSIBLE_NODE_H
 #include "config.h"
 
+#include "AccessibleUtils.h"
+
 #include <atspi/atspi.h>
 #include <map>
 #include <memory>
@@ -91,19 +93,17 @@ public:
 };
 
 class AccessibleNode {
-private:
+public:
     AccessibleNode();
     AccessibleNode(AtspiAccessible *node);
-
-public:
-    static AccessibleNode *get(AtspiAccessible *node);
     ~AccessibleNode();
+    static std::unique_ptr<AccessibleNode> get(AtspiAccessible *node);
 
 public:
     int              getChildCount() const;
-    AccessibleNode * getChildAt(int index) const;
-    AccessibleNode * getParent() const;
-    AtspiAccessible *getAccessible();
+    std::unique_ptr<AccessibleNode> getChildAt(int index) const;
+    std::unique_ptr<AccessibleNode> getParent() const;
+    AtspiAccessible *getAccessible() const;
 
 public:
     std::string getDesc() const;
@@ -140,7 +140,7 @@ private:
     static std::map<AtspiAccessible *, AccessibleNode *> mNodeMap;
 
 private:
-    AtspiAccessible *mNode;
+    unique_ptr_gobj<AtspiAccessible> mNode;
 
     mutable std::string mText;
     mutable std::string mPkg;
index 42247f4..b779a23 100644 (file)
@@ -50,8 +50,8 @@ public:
     virtual ~AccessibleWatcher();
 
 public:
-    AccessibleNode *getRootNode() const;
-    AccessibleNode *getTopNode() const;
+    std::unique_ptr<AccessibleNode> getRootNode() const;
+    std::vector<std::unique_ptr<AccessibleNode>> getTopNode() const;
 
     void onWindowActivated(AtspiAccessible *      node,
                                    WindowActivateInfoType type) override;
index ce662ef..80f2313 100644 (file)
 
 class Comparer {
 private:
-    Comparer(const UiDevice *device, const UiSelector *selector,
+    Comparer(const UiDevice *device, const std::shared_ptr<UiSelector> selector,
              const bool &earlyReturn);
     ~Comparer();
 
 public:
-    static AccessibleNode *              findObject(const UiDevice *      device,
-                                                    const UiSelector *    selector,
+    static std::unique_ptr<AccessibleNode>             findObject(const UiDevice *      device,
+                                                    const std::shared_ptr<UiSelector> selector,
                                                     const AccessibleNode *root);
-    static std::vector<AccessibleNode *> findObjects(
-        const UiDevice *device, const UiSelector *selector,
+    static std::vector<std::unique_ptr<AccessibleNode>> findObjects(
+        const UiDevice *device, const std::shared_ptr<UiSelector> selector,
         const AccessibleNode *root);
 
 private:
-    std::vector<AccessibleNode *> findObjects(const AccessibleNode *root);
-    std::vector<AccessibleNode *> findObjects(
+    std::vector<std::unique_ptr<AccessibleNode>> findObjects(const AccessibleNode *root);
+    std::vector<std::unique_ptr<AccessibleNode>> findObjects(
         const AccessibleNode *root, const int &index, const int &depth,
         std::list<std::shared_ptr<PartialMatch>> &partialMatches);
 
 private:
     std::unique_ptr<PartialMatch> accept(const AccessibleNode *node,
-                                         const UiSelector *    selector,
+                                         const std::shared_ptr<UiSelector> selector,
                                          const int &index, const int &depth,
                                          const int &relDepth);
 
 private:
-    const UiDevice *  mDevice;
-    const UiSelector *mSelector;
+    const UiDevice *mDevice;
+    const std::shared_ptr<UiSelector> mSelector;
     bool              mEarlyReturn;
 };
 
index 43b5483..b44ecbb 100644 (file)
@@ -12,11 +12,11 @@ class UiObject;
 class ISearchable {
 public:
     virtual ~ISearchable() {}
-    virtual bool hasObject(const UiSelector *selector) const = 0;
+    virtual bool hasObject(const std::shared_ptr<UiSelector> selector) const = 0;
     virtual std::unique_ptr<UiObject> findObject(
-        const UiSelector *selector) const = 0;
+        const std::shared_ptr<UiSelector> selector) const = 0;
     virtual std::vector<std::unique_ptr<UiObject>> findObjects(
-        const UiSelector *selector) const = 0;
+        const std::shared_ptr<UiSelector> selector) const = 0;
 };
 
 #endif
\ No newline at end of file
index 467310e..2ab0a1d 100644 (file)
@@ -12,27 +12,27 @@ class PartialMatch {
 private:
     PartialMatch();
 
-    const UiSelector *                       mSelector;
+    const std::shared_ptr<UiSelector>        mSelector;
     const int                                mDepth;
     std::list<std::shared_ptr<PartialMatch>> mPartialMatches;
 
 public:
-    PartialMatch(const UiSelector *selector, const int absDepth);
+    PartialMatch(const std::shared_ptr<UiSelector> selector, const int absDepth);
     void update(const AccessibleNode *node, int index, int depth,
                 std::list<std::shared_ptr<PartialMatch>> &partialMatches);
     bool finalizeMatch();
 
 public:
     static std::shared_ptr<PartialMatch> accept(const AccessibleNode *node,
-                                                const UiSelector *    selector,
+                                                const std::shared_ptr<UiSelector> selector,
                                                 int index, int depth);
     static std::shared_ptr<PartialMatch> accept(const AccessibleNode *node,
-                                                const UiSelector *    selector,
+                                                const std::shared_ptr<UiSelector> selector,
                                                 int index, int absoluteDepth,
                                                 int relativeDepth);
 
 private:
-    static bool checkCriteria(const UiSelector *    sel,
+    static bool checkCriteria(const std::shared_ptr<UiSelector> selector,
                               const AccessibleNode *node);
 };
 
index cc67193..ef3c7d6 100644 (file)
@@ -9,9 +9,9 @@
 
 class Sel {
 public:
-    static std::unique_ptr<UiSelector> text(const std::string &text);
-    static std::unique_ptr<UiSelector> type(const std::string &text);
-    static std::unique_ptr<UiSelector> depth(const int &depth);
+    static std::shared_ptr<UiSelector> text(const std::string &text);
+    static std::shared_ptr<UiSelector> type(const std::string &text);
+    static std::shared_ptr<UiSelector> depth(const int &depth);
 };
 
 #endif
\ No newline at end of file
index 66b1b84..88417f7 100644 (file)
@@ -43,11 +43,11 @@ public:
     bool takeScreenshot(std::string path, float scale, int quality);
 
 public:
-    bool hasObject(const UiSelector *selector) const override;
+    bool hasObject(const std::shared_ptr<UiSelector> selector) const override;
     std::unique_ptr<UiObject> findObject(
-        const UiSelector *selector) const override;
+        const std::shared_ptr<UiSelector> selector) const override;
     std::vector<std::unique_ptr<UiObject>> findObjects(
-        const UiSelector *selector) const override;
+        const std::shared_ptr<UiSelector> selector) const override;
 
     bool waitFor(
         const std::function<bool(const ISearchable *)> condition) const;
@@ -59,7 +59,7 @@ public:
     static UiDevice *getInstance(DeviceType type);
 
 private:
-    const AccessibleNode *getWindowRoot() const;
+    const std::vector<std::unique_ptr<AccessibleNode>> getWindowRoot() const;
 
 private:
     UiDevice();
index d6ff0d9..4b1b0f7 100644 (file)
@@ -14,18 +14,22 @@ class UiDevice;
 
 class UiObject : public ISearchable {
 public:
-    UiObject(const UiDevice *device, const UiSelector *selector,
+    UiObject(const UiDevice *device, const std::shared_ptr<UiSelector> selector,
              const AccessibleNode *node);
-    UiObject(const UiObject &src);  // copy constroctur
+
+    UiObject(const UiDevice *device, const std::shared_ptr<UiSelector> selector,
+             std::unique_ptr<AccessibleNode> node);
+
+//    UiObject(const UiObject &src);  // copy constroctur
     UiObject(UiObject &&src);       // move constructor
 
     virtual ~UiObject();
 
-    bool hasObject(const UiSelector *selector) const override;
+    bool hasObject(const std::shared_ptr<UiSelector> selector) const override;
     std::unique_ptr<UiObject> findObject(
-        const UiSelector *selector) const override;
+        const std::shared_ptr<UiSelector> selector) const override;
     std::vector<std::unique_ptr<UiObject>> findObjects(
-        const UiSelector *selector) const override;
+        const std::shared_ptr<UiSelector> selector) const override;
 
     bool waitFor(
         const std::function<bool(const ISearchable *)> condition) const;
@@ -71,9 +75,10 @@ private:
 
 private:
     const UiDevice *      mDevice;
-    const UiSelector *    mSelector;
-    const AccessibleNode *mNode;
+    std::shared_ptr<UiSelector>  mSelector;
+    std::unique_ptr<AccessibleNode> mNode;
     const Waiter *        mWaiter;
+    //std::unique_ptr<AccessibleNode> mNode_src;
 };
 
 #endif
\ No newline at end of file
index 997ad79..735ad12 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <string>
 #include <vector>
+#include <memory>
 
 class UiSelector {
 public:
@@ -22,7 +23,7 @@ public:
 
     UiSelector *depth(int depth);
 
-    UiSelector *hasChild(UiSelector *child);
+    UiSelector *hasChild(std::shared_ptr<UiSelector> child);
 
 public:
     std::string mText;
@@ -32,7 +33,7 @@ public:
     std::string mType;
     int         mDepth;
 
-    std::vector<UiSelector *> mChild;
+    std::vector<std::shared_ptr<UiSelector>> mChild;
 };
 
 #endif
\ No newline at end of file
index fc80795..b732c45 100644 (file)
@@ -8,7 +8,7 @@
 class Until {
 private:
     Until();
-    Until(const UiSelector *selector);
+    Until(const std::shared_ptr<UiSelector> selector);
     Until(const Until &src);
     Until(const Until &&src);
 
@@ -17,9 +17,9 @@ public:
 
 public:
     static std::function<bool(const ISearchable *)> hasObject(
-        const UiSelector *selector);
+        const std::shared_ptr<UiSelector> selector);
     static std::function<std::unique_ptr<UiObject>(const ISearchable *)>
-                                                 findObject(const UiSelector *selector);
+                                                 findObject(const std::shared_ptr<UiSelector> selector);
     static std::function<bool(const UiObject *)> checkable(
         const bool isCheckable);
 };
index 6f25089..0de1c62 100644 (file)
@@ -3,14 +3,13 @@
 #include <iostream>
 
 #include "loguru.hpp"
-
 #include "config.h"
 
 std::map<AtspiAccessible *, AccessibleNode *> AccessibleNode::mNodeMap{};
 
 AccessibleNode::~AccessibleNode()
 {
-    g_object_unref(mNode);
+
 }
 
 AccessibleNode::AccessibleNode() : AccessibleNode(nullptr)
@@ -20,13 +19,13 @@ AccessibleNode::AccessibleNode() : AccessibleNode(nullptr)
 }
 
 AccessibleNode::AccessibleNode(AtspiAccessible *node)
-    : mNode(node), mBoundingBox{0,0,0,0}, mSupportingIfaces(0), mFeatureProperty(0), mIsAlive(true)
+    : mNode(make_gobj_ref_unique(node)), mBoundingBox{0,0,0,0}, mSupportingIfaces(0), mFeatureProperty(0), mIsAlive(true)
 {
     // prohibited to create this object this constructor
     // better to use AccessibleNode::get factory method.
-    LOG_SCOPE_F(1, "AccessibleNode constructor %p", node);
-    g_object_ref(node);
-    GArray *ifaces = atspi_accessible_get_interfaces(mNode);
+
+    LOG_SCOPE_F(1, "AccessibleNode constructor %p", mNode.get());
+    GArray *ifaces = atspi_accessible_get_interfaces(mNode.get());
     if (ifaces) {
         for (unsigned int i = 0; i < ifaces->len; i++) {
             char *iface = g_array_index(ifaces, char *, i);
@@ -76,32 +75,25 @@ AccessibleNode::AccessibleNode(AtspiAccessible *node)
     this->refresh();
 }
 
-AccessibleNode *AccessibleNode::get(AtspiAccessible *node)
+std::unique_ptr<AccessibleNode> AccessibleNode::get(AtspiAccessible *node)
 {
-    LOG_SCOPE_F(9, "Accessible Node Factory %p", node);
-    if (node == nullptr) return nullptr;
-
-    AccessibleNode *cache = mNodeMap[node];
-    LOG_F(9, "Cache hit ? %p", cache);
-
-    if (!cache)
-        mNodeMap[node] = new AccessibleNode(node);
-    else
-        cache->refresh();
-
-    return mNodeMap[node];
+    return std::make_unique<AccessibleNode>(node);
 }
 
 void AccessibleNode::refresh() const
 {
-    gchar *rolename = atspi_accessible_get_role_name(mNode, NULL);
-    mRole = rolename;
-    g_free(rolename);
+    gchar *rolename = atspi_accessible_get_role_name(mNode.get(), NULL);
+    if (rolename) {
+        mRole = rolename;
+        g_free(rolename);
+    }
 
 #ifdef GBS_BUILD
-    gchar *uID = atspi_accessible_get_unique_id(mNode, NULL);
-    mRes = uID;
-    g_free(uID);
+    gchar *uID = atspi_accessible_get_unique_id(mNode.get(), NULL);
+    if (uID) {
+        mRes = uID;
+        g_free(uID);
+    }
 #else
     mRes = "Not_Supported";
 #endif
@@ -125,22 +117,25 @@ void AccessibleNode::refresh() const
 
 int AccessibleNode::getChildCount() const
 {
-    return atspi_accessible_get_child_count(mNode, NULL);
+    return atspi_accessible_get_child_count(mNode.get(), NULL);
 }
 
-AccessibleNode *AccessibleNode::getChildAt(int index) const
+std::unique_ptr<AccessibleNode> AccessibleNode::getChildAt(int index) const
 {
     AtspiAccessible *child =
-        atspi_accessible_get_child_at_index(mNode, index, NULL);
-    AccessibleNode *node = AccessibleNode::get(child);
-    if (child) g_object_unref(child);
-    return node;
+        atspi_accessible_get_child_at_index(mNode.get(), index, NULL);
+    if (child) {
+        auto node = AccessibleNode::get(child);
+        g_object_unref(child);
+        return node;
+    }
+    return AccessibleNode::get(nullptr);
 }
 
-AccessibleNode *AccessibleNode::getParent() const
+std::unique_ptr<AccessibleNode> AccessibleNode::getParent() const
 {
-    AtspiAccessible *parent = atspi_accessible_get_parent(mNode, NULL);
-    AccessibleNode * node = AccessibleNode::get(parent);
+    AtspiAccessible *parent = atspi_accessible_get_parent(mNode.get(), NULL);
+    auto node = AccessibleNode::get(parent);
     if (parent) g_object_unref(parent);
     return node;
 }
@@ -150,23 +145,21 @@ void AccessibleNode::print(int d, int m) const
     if (m <= 0 || d > m) return;
 
     int             n = 0;
-    AccessibleNode *child = nullptr;
-
     this->print(d);
     n = getChildCount();
 
     for (int i = 0; i < n; i++) {
-        child = getChildAt(i);
+        auto child = getChildAt(i);
         if (child) child->print(d + 1, m);
     }
 }
 
 void AccessibleNode::print(int d) const
 {
-    char *name = atspi_accessible_get_name(mNode, NULL);
-    char *role = atspi_accessible_get_role_name(mNode, NULL);
+    char *name = atspi_accessible_get_name(mNode.get(), NULL);
+    char *role = atspi_accessible_get_role_name(mNode.get(), NULL);
     LOG_F(INFO, "%s - %p(%s)  /  role:%s, pkg:%s, text:%s",
-          std::string(d, ' ').c_str(), mNode, name, role, getPkg().c_str(),
+          std::string(d, ' ').c_str(), mNode.get(), name, role, getPkg().c_str(),
           getText().c_str());
     free(name);
     free(role);
@@ -197,7 +190,7 @@ std::string AccessibleNode::getDesc() const
 
 std::string AccessibleNode::getText() const
 {
-    gchar *name = atspi_accessible_get_name(mNode, NULL);
+    gchar *name = atspi_accessible_get_name(mNode.get(), NULL);
     mText = name;
     mPkg = name;
     g_free(name);
@@ -220,7 +213,7 @@ std::string AccessibleNode::getType() const
 }
 Rect<int> AccessibleNode::getBoundingBox() const
 {
-    AtspiComponent *component = atspi_accessible_get_component_iface(mNode);
+    AtspiComponent *component = atspi_accessible_get_component_iface(mNode.get());
     if (component) {
         AtspiRect *extent = atspi_component_get_extents(
             component, ATSPI_COORD_TYPE_SCREEN, NULL);
@@ -291,14 +284,14 @@ bool AccessibleNode::isVisible() const
     return hasFeatureProperty(NodeFeatureProperties::VISIBILITY);
 }
 
-AtspiAccessible *AccessibleNode::getAccessible()
+AtspiAccessible *AccessibleNode::getAccessible() const
 {
-    return mNode;
+    return mNode.get();
 }
 
 void AccessibleNode::setValue(std::string &text) const
 {
-    AtspiEditableText *iface = atspi_accessible_get_editable_text(mNode);
+    AtspiEditableText *iface = atspi_accessible_get_editable_text(mNode.get());
     if (iface) {
         atspi_editable_text_insert_text(iface, 0, text.c_str(), text.length(),
                                         NULL);
index 5e0de48..a24a545 100644 (file)
@@ -9,56 +9,51 @@
 
 AtspiEventListener *AccessibleWatcher::listener = nullptr;
 
-static bool iShowingNode(AtspiAccessible *node)
-{
-    char *name = atspi_accessible_get_name(node, NULL);
-    char *pname = atspi_accessible_get_name(
-        atspi_accessible_get_parent(node, NULL), NULL);
 
-    LOG_SCOPE_F(INFO, "isShowing %s %s", name, pname);
 
-    // if (!strcmp(name, "Keyboard") && !strcmp(pname, "ise-default")) {
-    //     free(name);
-    //     free(pname);
-    //     return false;
-    // }
-    free(name);
-    free(pname);
-
-    AtspiStateSet *stateSet = atspi_accessible_get_state_set(node);
-    if (atspi_state_set_contains(stateSet, ATSPI_STATE_ACTIVE) &&
-        atspi_state_set_contains(stateSet, ATSPI_STATE_SHOWING)) {
-        g_object_unref(stateSet);
+static bool iShowingNode(AtspiAccessible *node)
+{
+    char *name = NULL;
+    if (node) name = atspi_accessible_get_name(node, NULL);
+    else return false;
+
+    LOG_SCOPE_F(INFO, "isShowing %s", name);
+    auto stateSet = make_gobj_unique(atspi_accessible_get_state_set(node));
+    auto states = make_garray_unique(atspi_state_set_get_states(stateSet.get()));
+
+    if (atspi_state_set_contains(stateSet.get(), ATSPI_STATE_ACTIVE)
+        && atspi_state_set_contains(stateSet.get(), ATSPI_STATE_SHOWING)) {
+        LOG_F(INFO, "active and showing %p %s", node, name);
+        free(name);
         return true;
     }
+    free(name);
     return false;
 }
 
-static AtspiAccessible *findActiveNode(AtspiAccessible *node, int depth,
+static std::vector<AtspiAccessible *>
+findActiveNode(AtspiAccessible *node, int depth,
                                        int max_depth)
 {
-    if (depth >= max_depth) return NULL;
+    std::vector<AtspiAccessible *> ret{};
+    if (depth >= max_depth) return ret;
 
     if (iShowingNode(node)) {
         g_object_ref(node);
-
         char *name = atspi_accessible_get_name(node, NULL);
-        char *pname = atspi_accessible_get_name(
-            atspi_accessible_get_parent(node, NULL), NULL);
-        LOG_SCOPE_F(INFO, "%s %s", name, pname);
-        return node;
+        LOG_SCOPE_F(INFO, "%s", name);
+        ret.push_back(node);
+        return ret;
     }
 
     int nchild = atspi_accessible_get_child_count(node, NULL);
     for (int i = 0; i < nchild; i++) {
-        AtspiAccessible *child =
-            atspi_accessible_get_child_at_index(node, i, NULL);
-        AtspiAccessible *active = findActiveNode(child, depth + 1, max_depth);
-        g_object_unref(child);
-        if (active) return active;
+        auto child = make_gobj_unique(atspi_accessible_get_child_at_index(node, i, NULL));
+        std::vector<AtspiAccessible *> childRet = findActiveNode(child.get(), depth + 1, max_depth);
+        ret.insert(ret.end(), childRet.begin(), childRet.end());
     }
 
-    return NULL;
+    return ret;
 }
 
 AccessibleWatcher::AccessibleWatcher() : mActivatedWindowList{}, mWindowSet{}
@@ -121,57 +116,83 @@ AccessibleWatcher::~AccessibleWatcher()
     atspi_exit();
 }
 
-AccessibleNode *AccessibleWatcher::getRootNode() const
+std::unique_ptr<AccessibleNode> AccessibleWatcher::getRootNode() const
 {
-    AtspiAccessible *node = atspi_get_desktop(0);
-    AccessibleNode * accNode = AccessibleNode::get(node);
-    if (node) g_object_unref(node);
+    auto node = make_gobj_unique(atspi_get_desktop(0));
+    auto accNode = AccessibleNode::get(node.get());
+    if(node.get()) g_object_unref(node.get());
     return accNode;
 }
 
-AccessibleNode *AccessibleWatcher::getTopNode() const
+std::vector<std::unique_ptr<AccessibleNode>> AccessibleWatcher::getTopNode() const
 {
-    AtspiAccessible *topNode = nullptr, *activeNode = nullptr,
-                    *rootNode = nullptr;
+    AtspiAccessible *topNode = nullptr, *activeNode = nullptr;
+    std::vector<std::unique_ptr<AccessibleNode>> ret;
+
     {
         std::unique_lock<std::mutex> lock(mLock);
         if (!mActivatedWindowList.empty()) {
             topNode = mActivatedWindowList.front();
-            if (topNode && iShowingNode(topNode))
-                return AccessibleNode::get(atspi_accessible_get_application(topNode, NULL));
+            std::list<AtspiAccessible *>::const_iterator iterator;
+            for (iterator = mActivatedWindowList.begin(); iterator != mActivatedWindowList.end(); ++iterator){
+                if (*iterator && iShowingNode(*iterator)) {
+                    AtspiAccessible *child = atspi_accessible_get_application(*iterator, NULL);
+                    if (child) {
+                        auto tmpNode = make_gobj_unique(child);
+                        auto node =  AccessibleNode::get(tmpNode.get());
+                        if (tmpNode.get()) g_object_unref(tmpNode.get());
+                        ret.push_back(std::move(node));
+                    }
+                }
+            }
+            return ret;
         }
     }
 
     LOG_F(INFO, "Mo activated window node or Invisible acticated window / topNdoe(%p)", topNode);
     LOG_F(INFO, "Trying fallback logic");
 
-    rootNode = atspi_get_desktop(0);
+    auto rootNode = make_gobj_unique(atspi_get_desktop(0));
 
     if (rootNode) {
-        activeNode = atspi_accessible_get_application(findActiveNode(rootNode, 0, 2), NULL);
-        if (activeNode) {
-            AccessibleNode *node = AccessibleNode::get(activeNode);
-            return node;
+        std::vector<AtspiAccessible*> activeNodes = findActiveNode(rootNode.get(), 0, 2);
+        if (!activeNodes.empty()) {
+            std::vector<AtspiAccessible*>::const_iterator iterator;
+            for (iterator = activeNodes.begin(); iterator != activeNodes.end(); ++iterator){
+                auto tmpNode = make_gobj_unique(atspi_accessible_get_application(*iterator, NULL));
+                auto node = AccessibleNode::get(tmpNode.get());
+                if (tmpNode.get()) g_object_unref(tmpNode.get());
+                g_object_unref(*iterator);
+                ret.push_back(std::move(node));
+            }
+        } else {
+            auto node = AccessibleNode::get(rootNode.get());
+            if (rootNode.get()) g_object_unref(rootNode.get());
+            ret.push_back(std::move(node));
         }
-        AccessibleNode *node = AccessibleNode::get(rootNode);
-        return node;
     }
-    return nullptr;
+    return ret;
 }
 
 void AccessibleWatcher::onAtspiWindowEvent(AtspiEvent *event, void *user_data)
 {
-    char *              name, *pname;
+    char *name = NULL, *pname = NULL;
     IAtspiEvents *instance = (IAtspiEvents *)user_data;
 
-    AtspiAccessible *p = atspi_accessible_get_parent(event->source, NULL);
+    if (!event->source)
+    {
+        LOG_F(INFO, "event->source is NULL. Skip event handling");
+        return;
+    }
+
+    auto p = make_gobj_unique(atspi_accessible_get_parent(event->source, NULL));
 
     name = atspi_accessible_get_name(event->source, NULL);
-    pname = atspi_accessible_get_name(p, NULL);
+    if (p) pname = atspi_accessible_get_name(p.get(), NULL);
 
-    // LOG_SCOPE_F(INFO, "event:%s, src:%p(%s), p:%p(%s), d1:%p d2:%p instance:%p",
-    //             event->type, event->source, name, p, pname, event->detail1,
-    //             event->detail2, instance);
+     LOG_SCOPE_F(INFO, "event:%s, src:%p(%s), p:%p(%s), d1:%p d2:%p instance:%p",
+                 event->type, event->source, name, p.get(), pname, event->detail1,
+                 event->detail2, instance);
 
     if (!strcmp(event->type, "window:activate")) {
         instance->onWindowActivated(
@@ -191,6 +212,8 @@ void AccessibleWatcher::onAtspiWindowEvent(AtspiEvent *event, void *user_data)
         instance->onObjectDefunct(
             static_cast<AtspiAccessible *>(event->source));
     }
+    if (name) free(name);
+    if (pname) free(pname);
 }
 
 void AccessibleWatcher::printDbgInformation() const
@@ -235,7 +258,6 @@ bool AccessibleWatcher::removeFromActivatedList(AtspiAccessible *node)
 bool AccessibleWatcher::addToActivatedList(AtspiAccessible *node)
 {
     mActivatedWindowList.remove_if([&](auto &n) { return n == node; });
-    //if (!strcmp(name, "Keyboard") && !strcmp(pname, "ise-default")) return;
     mActivatedWindowList.push_front(node);
 
     auto iter = mWindowSet.find(node);
@@ -268,20 +290,8 @@ void AccessibleWatcher::onWindowActivated(AtspiAccessible *      node,
                             WindowActivateInfoType type)
 {
     std::unique_lock<std::mutex> lock(mLock);
-
     addToActivatedList(node);
-
     return;
-    /*
-    char *name = atspi_accessible_get_name(node, NULL);
-    char *pname = atspi_accessible_get_name(
-        atspi_accessible_get_parent(node, NULL), NULL);
-    LOG_SCOPE_F(INFO, "%s %s", name, pname);
-
-    mActivatedWindowList.remove_if([&](auto &n) { return n == node; });
-    if (!strcmp(name, "Keyboard") && !strcmp(pname, "ise-default")) return;
-    mActivatedWindowList.push_front(node);
-    */
 }
 
 void AccessibleWatcher::onWindowDeactivated(AtspiAccessible *node)
@@ -289,10 +299,6 @@ void AccessibleWatcher::onWindowDeactivated(AtspiAccessible *node)
     std::unique_lock<std::mutex> lock(mLock);
     removeFromActivatedList(node);
     return;
-/*
-    mActivatedWindowList.remove_if([&](auto &n) { return n == node; });
-    mActivatedWindowList.push_back(node);
-    */
 }
 
 void AccessibleWatcher::onWindowCreated(AtspiAccessible *node)
index 9a1e777..ac3ffb9 100644 (file)
@@ -2,7 +2,7 @@
 
 #include "loguru.hpp"
 
-Comparer::Comparer(const UiDevice *device, const UiSelector *selector,
+Comparer::Comparer(const UiDevice *device, const std::shared_ptr<UiSelector> selector,
                    const bool &earlyReturn)
     : mDevice(device), mSelector(selector), mEarlyReturn(earlyReturn)
 {
@@ -10,44 +10,41 @@ Comparer::Comparer(const UiDevice *device, const UiSelector *selector,
 
 Comparer::~Comparer() {}
 
-AccessibleNode *Comparer::findObject(const UiDevice *      device,
-                                     const UiSelector *    selector,
+std::unique_ptr<AccessibleNode> Comparer::findObject(const UiDevice *      device,
+                                     const std::shared_ptr<UiSelector> selector,
                                      const AccessibleNode *root)
 {
     Comparer                      comparer(device, selector, true);
-    std::vector<AccessibleNode *> ret = comparer.findObjects(root);
+    std::vector<std::unique_ptr<AccessibleNode>> ret = comparer.findObjects(root);
     if (ret.size() > 0)
-        return ret[0];
+        return std::move(ret[0]);
     else
         return nullptr;
 }
 
-std::vector<AccessibleNode *> Comparer::findObjects(const UiDevice *  device,
-                                                    const UiSelector *selector,
+std::vector<std::unique_ptr<AccessibleNode>> Comparer::findObjects(const UiDevice *  device,
+                                                    const std::shared_ptr<UiSelector> selector,
                                                     const AccessibleNode *root)
 {
     Comparer                      comparer(device, selector, false);
-    std::vector<AccessibleNode *> ret = comparer.findObjects(root);
-    return std::move(ret);
+    std::vector<std::unique_ptr<AccessibleNode>> ret = comparer.findObjects(root);
+    return ret;
 }
 
-std::vector<AccessibleNode *> Comparer::findObjects(const AccessibleNode *root)
+std::vector<std::unique_ptr<AccessibleNode>> Comparer::findObjects(const AccessibleNode *root)
 {
     std::list<std::shared_ptr<PartialMatch>> partialList{};
-    std::vector<AccessibleNode *> ret = findObjects(root, 0, 0, partialList);
-    return std::move(ret);
+    std::vector<std::unique_ptr<AccessibleNode>> ret = findObjects(root, 0, 0, partialList);
+    return ret;
 }
 
-std::vector<AccessibleNode *> Comparer::findObjects(
+std::vector<std::unique_ptr<AccessibleNode>> Comparer::findObjects(
     const AccessibleNode *root, const int &index, const int &depth,
     std::list<std::shared_ptr<PartialMatch>> &partialMatches)
 {
-    std::vector<AccessibleNode *> ret;
+    std::vector<std::unique_ptr<AccessibleNode>> ret;
     root->refresh();
 
-    // LOG_F(INFO, "%p %s / i:%d d:%d", root, root->getText().c_str(), index,
-    // depth);
-
     for (auto match : partialMatches)
         match->update(root, index, depth, partialMatches);
 
@@ -57,16 +54,16 @@ std::vector<AccessibleNode *> Comparer::findObjects(
 
     int childCnt = root->getChildCount();
     for (int i = 0; i < childCnt; i++) {
-        AccessibleNode *              childNode = root->getChildAt(i);
-        std::vector<AccessibleNode *> childret =
-            findObjects(childNode, i, depth + 1, partialMatches);
-        ret.insert(ret.end(), childret.begin(), childret.end());
+        std::unique_ptr<AccessibleNode> childNode = root->getChildAt(i);
+        std::vector<std::unique_ptr<AccessibleNode>> childret =
+            findObjects(childNode.get(), i, depth + 1, partialMatches);
+        std::move(std::begin(childret), std::end(childret), std::back_inserter(ret));
 
         if (!ret.empty() && mEarlyReturn) return ret;
     }
 
     if (currentMatch && currentMatch->finalizeMatch())
-        ret.push_back(const_cast<AccessibleNode *>(root));
+        ret.push_back(AccessibleNode::get(root->getAccessible()));
 
     return ret;
 }
\ No newline at end of file
index 7d57236..18143ac 100644 (file)
@@ -5,30 +5,30 @@
 
 #include "loguru.hpp"
 
-bool PartialMatch::checkCriteria(const UiSelector *    sel,
+bool PartialMatch::checkCriteria(const std::shared_ptr<UiSelector> selector,
                                  const AccessibleNode *node)
 {
-    if (sel->mPkg.length() > 0 && sel->mPkg.compare(node->getPkg()))
+    if (selector->mPkg.length() > 0 && selector->mPkg.compare(node->getPkg()))
         return false;
-    if (sel->mRes.length() > 0 && sel->mRes.compare(node->getRes()))
+    if (selector->mRes.length() > 0 && selector->mRes.compare(node->getRes()))
         return false;
-    if (sel->mText.length() > 0 && sel->mText.compare(node->getText()))
+    if (selector->mText.length() > 0 && selector->mText.compare(node->getText()))
         return false;
-    if (sel->mDesc.length() > 0 && sel->mDesc.compare(node->getDesc()))
+    if (selector->mDesc.length() > 0 && selector->mDesc.compare(node->getDesc()))
         return false;
-    if (sel->mType.length() > 0 && sel->mType.compare(node->getType()))
+    if (selector->mType.length() > 0 && selector->mType.compare(node->getType()))
         return false;
 
-    LOG_F(INFO, "node mPkg :%s, sel->desc :%s | %ld", node->getPkg().c_str(),
-          sel->mPkg.c_str(), sel->mPkg.length());
-    LOG_F(INFO, "node mRes :%s, sel->desc :%s | %ld", node->getRes().c_str(),
-          sel->mRes.c_str(), sel->mRes.length());
-    LOG_F(INFO, "node mText :%s, sel->desc :%s | %ld", node->getText().c_str(),
-          sel->mText.c_str(), sel->mText.length());
-    LOG_F(INFO, "node mDesc :%s, sel->desc :%s | %ld", node->getDesc().c_str(),
-          sel->mDesc.c_str(), sel->mDesc.length());
-    LOG_F(INFO, "node mType :%s, sel->type :%s | %ld", node->getType().c_str(),
-          sel->mType.c_str(), sel->mType.length());
+    LOG_F(INFO, "node mPkg :%s, selector->desc :%s | %ld", node->getPkg().c_str(),
+          selector->mPkg.c_str(), selector->mPkg.length());
+    LOG_F(INFO, "node mRes :%s, selector->desc :%s | %ld", node->getRes().c_str(),
+          selector->mRes.c_str(), selector->mRes.length());
+    LOG_F(INFO, "node mText :%s, selector->desc :%s | %ld", node->getText().c_str(),
+          selector->mText.c_str(), selector->mText.length());
+    LOG_F(INFO, "node mDesc :%s, selector->desc :%s | %ld", node->getDesc().c_str(),
+          selector->mDesc.c_str(), selector->mDesc.length());
+    LOG_F(INFO, "node mType :%s, selector->type :%s | %ld", node->getType().c_str(),
+          selector->mType.c_str(), selector->mType.length());
 
     return true;
 }
@@ -37,20 +37,20 @@ PartialMatch::PartialMatch() : mSelector{nullptr}, mDepth{-1}, mPartialMatches{}
 {
 }
 
-PartialMatch::PartialMatch(const UiSelector *selector, const int absDepth)
+PartialMatch::PartialMatch(const std::shared_ptr<UiSelector> selector, const int absDepth)
     : mSelector{selector}, mDepth{absDepth}, mPartialMatches{}
 {
 }
 
 std::shared_ptr<PartialMatch> PartialMatch::accept(const AccessibleNode *node,
-                                                   const UiSelector *selector,
+                                                   const std::shared_ptr<UiSelector> selector,
                                                    int index, int depth)
 {
     return PartialMatch::accept(node, selector, index, depth, depth);
 }
 
 std::shared_ptr<PartialMatch> PartialMatch::accept(const AccessibleNode *node,
-                                                   const UiSelector *selector,
+                                                   const std::shared_ptr<UiSelector> selector,
                                                    int index, int absoluteDepth,
                                                    int relativeDepth)
 {
@@ -80,10 +80,10 @@ void PartialMatch::update(
 
 bool PartialMatch::finalizeMatch()
 {
-    std::set<UiSelector *> matches;
+    std::set<std::shared_ptr<UiSelector>> matches;
     for (auto match : mPartialMatches) {
         if (match->finalizeMatch()) {
-            matches.insert(const_cast<UiSelector *>(match->mSelector));
+            matches.insert(match->mSelector);
         }
     }
 
index 38be464..f5d0457 100644 (file)
@@ -1,23 +1,23 @@
 #include "Sel.h"
 #include <utility>
 
-std::unique_ptr<UiSelector> Sel::text(const std::string &text)
+std::shared_ptr<UiSelector> Sel::text(const std::string &text)
 {
-    std::unique_ptr<UiSelector> sel = std::make_unique<UiSelector>();
+    std::shared_ptr<UiSelector> sel = std::make_shared<UiSelector>();
     sel->text(text);
     return sel;
 }
 
-std::unique_ptr<UiSelector> Sel::type(const std::string &text)
+std::shared_ptr<UiSelector> Sel::type(const std::string &text)
 {
-    std::unique_ptr<UiSelector> sel = std::make_unique<UiSelector>();
+    std::shared_ptr<UiSelector> sel = std::make_shared<UiSelector>();
     sel->type(text);
     return sel;
 }
 
-std::unique_ptr<UiSelector> Sel::depth(const int &depth)
+std::shared_ptr<UiSelector> Sel::depth(const int &depth)
 {
-    std::unique_ptr<UiSelector> sel = std::make_unique<UiSelector>();
+    std::shared_ptr<UiSelector> sel = std::make_shared<UiSelector>();
     sel->depth(depth);
     return sel;
 }
\ No newline at end of file
index 5d12186..fb65535 100644 (file)
@@ -29,41 +29,50 @@ UiDevice *UiDevice::getInstance(DeviceType type)
     return device;
 }
 
-const AccessibleNode *UiDevice::getWindowRoot() const
+const std::vector<std::unique_ptr<AccessibleNode>> UiDevice::getWindowRoot() const
 {
-    AccessibleNode *root = AccessibleWatcher::getInstance()->getTopNode();
+    std::vector<std::unique_ptr<AccessibleNode>> root = AccessibleWatcher::getInstance()->getTopNode();
     // root->print(0,6);
     return root;
 }
 
-bool UiDevice::hasObject(const UiSelector *selector) const
+bool UiDevice::hasObject(const std::shared_ptr<UiSelector> selector) const
 {
-    AccessibleNode *node =
-        Comparer::findObject(this, selector, getWindowRoot());
-    if (node != nullptr) return true;
+    auto root = getWindowRoot();
+    for (auto it = root.begin(); it != root.end(); ++it) {
+        std::unique_ptr<AccessibleNode> node =
+            Comparer::findObject(this, selector, (*it).get());
+        if (node != nullptr) return true;
+    }
+
     return false;
 }
 
-std::unique_ptr<UiObject> UiDevice::findObject(const UiSelector *selector) const
+std::unique_ptr<UiObject> UiDevice::findObject(const std::shared_ptr<UiSelector> selector) const
 {
-    AccessibleNode *node =
-        Comparer::findObject(this, selector, getWindowRoot());
-    if (node)
-        return std::make_unique<UiObject>(this, selector, node);
-    else
-        return std::unique_ptr<UiObject>{nullptr};
+    auto root = getWindowRoot();
+    for (auto it = root.begin(); it != root.end(); ++it) {
+        std::unique_ptr<AccessibleNode> node =
+            Comparer::findObject(this, selector, (*it).get());
+        if (node)
+            return std::make_unique<UiObject>(this, selector, std::move(node));
+    }
+    return std::unique_ptr<UiObject>{nullptr};
 }
 
 std::vector<std::unique_ptr<UiObject>> UiDevice::findObjects(
-    const UiSelector *selector) const
+    const std::shared_ptr<UiSelector> selector) const
 {
     std::vector<std::unique_ptr<UiObject>> ret{};
-    std::vector<AccessibleNode *>          nodes =
-        Comparer::findObjects(this, selector, getWindowRoot());
-    for (const AccessibleNode *node : nodes)
-        ret.push_back(std::make_unique<UiObject>(this, selector, node));
-
-    return std::move(ret);
+    auto root = getWindowRoot();
+    for (auto it = root.begin(); it != root.end(); ++it) {
+        std::vector<std::unique_ptr<AccessibleNode>>          nodes =
+            Comparer::findObjects(this, selector, (*it).get());
+
+        for (auto &node : nodes)
+            ret.push_back(std::make_unique<UiObject>(this, selector, std::move(node)));
+    }
+    return ret;
 }
 bool UiDevice::waitFor(
     const std::function<bool(const ISearchable *)> condition) const
index 3520a79..f185dc0 100644 (file)
@@ -14,29 +14,38 @@ UiObject::~UiObject()
     if (mWaiter) delete mWaiter;
 }
 
-UiObject::UiObject(const UiDevice *device, const UiSelector *selector,
+UiObject::UiObject(const UiDevice *device, const std::shared_ptr<UiSelector> selector,
                    const AccessibleNode *node)
     : mDevice(device),
       mSelector(selector),
-      mNode(node),
+      mNode(std::unique_ptr<AccessibleNode>(const_cast<AccessibleNode*>(node))),
       mWaiter(new Waiter{this, this})
 {
-    // tood interface to interact with input interface
-    // mInputImple = mDevice->getInputInterface();
 }
 
-UiObject::UiObject(const UiObject &src)
-    : mDevice(src.mDevice),
-      mSelector(src.mSelector),
-      mNode(src.mNode),
-      mWaiter{src.mWaiter}
+UiObject::UiObject(const UiDevice *device, const std::shared_ptr<UiSelector> selector,
+                   std::unique_ptr<AccessibleNode> node)
+    : mDevice(device),
+      mSelector(selector),
+      mNode(std::move(node)),
+      mWaiter(new Waiter{this, this})
 {
 }
 
+// UiObject::UiObject(const UiObject &src)
+//     : mDevice(src.mDevice),
+//       mSelector(src.mSelector),
+//       mNode(src.mNode),
+//       mWaiter{src.mWaiter},
+//       mNode_src(std::move(src.mNode_src))
+
+// {
+// }
+
 UiObject::UiObject(UiObject &&src)
     : mDevice(src.mDevice),
-      mSelector(src.mSelector),
-      mNode(src.mNode),
+      mSelector(std::move(src.mSelector)),
+      mNode(std::move(src.mNode)),
       mWaiter{src.mWaiter}
 {
     src.mDevice = nullptr;
@@ -45,9 +54,9 @@ UiObject::UiObject(UiObject &&src)
     src.mWaiter = nullptr;
 }
 
-bool UiObject::hasObject(const UiSelector *selector) const
+bool UiObject::hasObject(const std::shared_ptr<UiSelector> selector) const
 {
-    AccessibleNode *node =
+    std::unique_ptr<AccessibleNode> node =
         Comparer::findObject(mDevice, selector, getAccessibleNode());
     if (node != nullptr) {
         // todo : what is this node.recycle()
@@ -56,18 +65,18 @@ bool UiObject::hasObject(const UiSelector *selector) const
     return false;
 }
 
-std::unique_ptr<UiObject> UiObject::findObject(const UiSelector *selector) const
+std::unique_ptr<UiObject> UiObject::findObject(const std::shared_ptr<UiSelector> selector) const
 {
-    AccessibleNode *node =
+    std::unique_ptr<AccessibleNode> node =
         Comparer::findObject(mDevice, selector, getAccessibleNode());
     if (node)
-        return std::make_unique<UiObject>(mDevice, selector, node);
+        return std::make_unique<UiObject>(mDevice, selector, std::move(node));
     else
         return std::unique_ptr<UiObject>{nullptr};
 }
 
 std::vector<std::unique_ptr<UiObject>> UiObject::findObjects(
-    const UiSelector *selector) const
+    const std::shared_ptr<UiSelector> selector) const
 {
     return std::vector<std::unique_ptr<UiObject>>{};
 }
@@ -94,9 +103,9 @@ bool UiObject::waitFor(
 
 UiObject *UiObject::getParent() const
 {
-    AccessibleNode *node = getAccessibleNode()->getParent();
+    std::unique_ptr<AccessibleNode> node = getAccessibleNode()->getParent();
     if (!node) return nullptr;
-    return new UiObject(mDevice, mSelector, node);
+    return new UiObject(mDevice, mSelector, std::move(node));
 }
 
 int UiObject::getChildCount() const
@@ -106,7 +115,7 @@ int UiObject::getChildCount() const
 
 std::vector<std::unique_ptr<UiObject>> UiObject::getChildren() const
 {
-    return findObjects(Sel::depth(1).get());
+    return findObjects(Sel::depth(1));
 }
 
 std::string UiObject::getContentDescription() const
@@ -208,7 +217,6 @@ void UiObject::click() const
     std::cout << rect.mTopLeft.x << ", " << rect.mTopLeft.y << std::endl;
     const Point2D<int> midPoint = rect.midPoint();
     const_cast<UiDevice *>(mDevice)->click(midPoint.x, midPoint.y);
-    // todo click implementation
 }
 
 void UiObject::longClick(const unsigned int intv) const
@@ -229,5 +237,5 @@ const AccessibleNode *UiObject::getAccessibleNode() const
     // mDevice->waitForIdle();
     // mNode->refresh();
 
-    return mNode;
+    return mNode.get();
 }
\ No newline at end of file
index c8dece4..f45257f 100644 (file)
@@ -55,7 +55,7 @@ UiSelector *UiSelector::depth(int depth)
     return this;
 }
 
-UiSelector *UiSelector::hasChild(UiSelector *child)
+UiSelector *UiSelector::hasChild(std::shared_ptr<UiSelector> child)
 {
     mChild.push_back(child);
     return this;
index c67fa2b..bd9385f 100644 (file)
@@ -4,7 +4,7 @@
 #include <loguru.hpp>
 
 std::function<bool(const ISearchable *)> Until::hasObject(
-    const UiSelector *selector)
+    const std::shared_ptr<UiSelector> selector)
 {
     return [=](const ISearchable *searchable) -> bool {
         LOG_SCOPE_F(INFO, "sel:%p, search:%p", selector, searchable);
@@ -14,7 +14,7 @@ std::function<bool(const ISearchable *)> Until::hasObject(
 }
 
 std::function<std::unique_ptr<UiObject>(const ISearchable *)> Until::findObject(
-    const UiSelector *selector)
+    const std::shared_ptr<UiSelector> selector)
 {
     return [=](const ISearchable *searchable) -> std::unique_ptr<UiObject> {
         LOG_SCOPE_F(INFO, "sel:%p, search:%p", selector, searchable);
index 2587e72..7e0c3e1 100644 (file)
@@ -27,6 +27,6 @@ TEST_F(UaTest, DeviceInit)
 
 TEST_F(UaTest, TextSelector)
 {
-    std::unique_ptr<UiSelector> sel = Sel::text("test");
+    std::shared_ptr<UiSelector> sel = Sel::text("test");
     ASSERT_NE(sel.get(), nullptr);
 }
\ No newline at end of file