1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef UI_VIEWS_ACCESSIBILITY_AX_AURA_OBJ_CACHE_H_
6 #define UI_VIEWS_ACCESSIBILITY_AX_AURA_OBJ_CACHE_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <memory>
12 #include <set>
13 #include <vector>
14 
15 #include "ui/accessibility/ax_enums.mojom-forward.h"
16 #include "ui/aura/client/focus_change_observer.h"
17 #include "ui/views/views_export.h"
18 
19 namespace base {
20 template <typename T>
21 class NoDestructor;
22 }  // namespace base
23 
24 namespace aura {
25 class Window;
26 }  // namespace aura
27 
28 namespace views {
29 class AXAuraObjWrapper;
30 class View;
31 class Widget;
32 
33 // A cache responsible for assigning id's to a set of interesting Aura views.
34 class VIEWS_EXPORT AXAuraObjCache : public aura::client::FocusChangeObserver {
35  public:
36   AXAuraObjCache();
37   AXAuraObjCache(const AXAuraObjCache&) = delete;
38   AXAuraObjCache& operator=(const AXAuraObjCache&) = delete;
39   ~AXAuraObjCache() override;
40 
41   class Delegate {
42    public:
43     virtual ~Delegate() = default;
44 
45     virtual void OnChildWindowRemoved(AXAuraObjWrapper* parent) = 0;
46     virtual void OnEvent(AXAuraObjWrapper* aura_obj,
47                          ax::mojom::Event event_type) = 0;
48   };
49 
50   // Get or create an entry in the cache. May return null if the View is not
51   // associated with a Widget.
52   AXAuraObjWrapper* GetOrCreate(View* view);
53 
54   // Get or create an entry in the cache.
55   AXAuraObjWrapper* GetOrCreate(Widget* widget);
56   AXAuraObjWrapper* GetOrCreate(aura::Window* window);
57 
58   // Creates an entry in this cache given a wrapper object. Use this method when
59   // creating a wrapper not backed by any of the supported views above. This
60   // cache will take ownership. Will replace an existing entry with the same id.
61   void CreateOrReplace(std::unique_ptr<AXAuraObjWrapper> obj);
62 
63   // Gets an id given an Aura view.
64   int32_t GetID(View* view) const;
65   int32_t GetID(Widget* widget) const;
66   int32_t GetID(aura::Window* window) const;
67 
68   // Removes an entry from this cache based on an Aura view.
69   void Remove(View* view);
70   void Remove(Widget* widget);
71 
72   // Removes |window| and optionally notifies delegate by sending an event on
73   // the |parent| if provided.
74   void Remove(aura::Window* window, aura::Window* parent);
75 
76   // Removes a view and all of its descendants from the cache.
77   void RemoveViewSubtree(View* view);
78 
79   // Lookup a cached entry based on an id.
80   AXAuraObjWrapper* Get(int32_t id);
81 
82   // Get all top level windows this cache knows about. Under classic ash and
83   // SingleProcessMash this is a list of per-display root windows.
84   void GetTopLevelWindows(std::vector<AXAuraObjWrapper*>* children);
85 
86   // Get the object that has focus.
87   AXAuraObjWrapper* GetFocus();
88 
89   // Send a notification that the focused view may have changed.
90   void OnFocusedViewChanged();
91 
92   // Tell our delegate to fire an event on a given object.
93   void FireEvent(AXAuraObjWrapper* aura_obj, ax::mojom::Event event_type);
94 
95   // Notifies this cache of a change in root window.
96   void OnRootWindowObjCreated(aura::Window* window);
97 
98   // Notifies this cache of a change in root window.
99   void OnRootWindowObjDestroyed(aura::Window* window);
100 
SetDelegate(Delegate * delegate)101   void SetDelegate(Delegate* delegate) { delegate_ = delegate; }
102 
103   // Changes the behavior of GetFocusedView() so that it only considers
104   // views within the given Widget, this enables making tests
105   // involving focus reliable.
set_focused_widget_for_testing(views::Widget * widget)106   void set_focused_widget_for_testing(views::Widget* widget) {
107     focused_widget_for_testing_ = widget;
108   }
109 
110  private:
111   friend class base::NoDestructor<AXAuraObjCache>;
112 
113   View* GetFocusedView();
114 
115   // aura::client::FocusChangeObserver override.
116   void OnWindowFocused(aura::Window* gained_focus,
117                        aura::Window* lost_focus) override;
118 
119   template <typename AuraViewWrapper, typename AuraView>
120   AXAuraObjWrapper* CreateInternal(
121       AuraView* aura_view,
122       std::map<AuraView*, int32_t>* aura_view_to_id_map);
123 
124   template <typename AuraView>
125   int32_t GetIDInternal(
126       AuraView* aura_view,
127       const std::map<AuraView*, int32_t>& aura_view_to_id_map) const;
128 
129   template <typename AuraView>
130   void RemoveInternal(AuraView* aura_view,
131                       std::map<AuraView*, int32_t>* aura_view_to_id_map);
132 
133   std::map<views::View*, int32_t> view_to_id_map_;
134   std::map<views::Widget*, int32_t> widget_to_id_map_;
135   std::map<aura::Window*, int32_t> window_to_id_map_;
136 
137   std::map<int32_t, std::unique_ptr<AXAuraObjWrapper>> cache_;
138 
139   Delegate* delegate_ = nullptr;
140 
141   std::set<aura::Window*> root_windows_;
142 
143   views::Widget* focused_widget_for_testing_ = nullptr;
144 };
145 
146 }  // namespace views
147 
148 #endif  // UI_VIEWS_ACCESSIBILITY_AX_AURA_OBJ_CACHE_H_
149