1 // Copyright (c) 2011 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 CHROME_FRAME_TEST_CHROME_FRAME_UI_TEST_UTILS_H_ 6 #define CHROME_FRAME_TEST_CHROME_FRAME_UI_TEST_UTILS_H_ 7 8 #include <oleacc.h> 9 10 #include <string> 11 #include <vector> 12 13 #include "base/files/file_path.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/win/scoped_comptr.h" 16 #include "base/win/scoped_variant.h" 17 #include "chrome_frame/test/win_event_receiver.h" 18 19 namespace gfx { 20 class Rect; 21 } 22 23 namespace chrome_frame_test { 24 25 // Wrapper for MSAA/IAccessible2 accessibility objects. IAccessible2 is an 26 // open standard which serves as a complement to MSAA and specifies additional 27 // interfaces and methods. Chrome currently supports a subset of this API. 28 // 29 // In MSAA, there are two types of objects. The first, called an object or full 30 // object, has its own IAccessible interface. The second, called a simple 31 // element, does not have its own IAccessible interface and cannot have 32 // children. Simple elements must be referenced by combination of the parent 33 // object and the element's id in MSAA. This class handles this distinction 34 // transparently to the client. 35 class AccObject : public base::RefCounted<AccObject> { 36 public: 37 typedef std::vector<scoped_refptr<AccObject> > RefCountedAccObjectVector; 38 39 // Creates an AccObject with an IAccessible and child id. |accessible| must 40 // not be NULL. |child_id| must always be CHILDID_SELF unless this AccObject 41 // is a simple element. 42 AccObject(IAccessible* accessible, int child_id = CHILDID_SELF); 43 44 // Creates an AccObject corresponding to the given window. May return NULL 45 // if there is not accessible object for the window. The client owns the 46 // created AccObject. 47 static AccObject* CreateFromWindow(HWND hwnd); 48 49 // Creates an AccObject corresponding to the object that generated a 50 // WinEvent. Returns NULL on failure. 51 static AccObject* CreateFromEvent(HWND hwnd, LONG object_id, LONG child_id); 52 53 // Creates an AccObject from querying the given IDispatch. May return NULL 54 // if the object does not implement IAccessible. The client owns the created 55 // AccObject. 56 static AccObject* CreateFromDispatch(IDispatch* dispatch); 57 58 // Creates an AccObject corresponding to the accessible object at the screen 59 // coordinates given. Returns NULL on failure. The client owns the created 60 // AccObject. 61 // Note: This does not work in Chrome. 62 static AccObject* CreateFromPoint(int x, int y); 63 64 // Performs the default action on this object. Returns whether the action 65 // performed successfully. Will cause test failure if unsuccessful. 66 // Note: This does not work for selecting menu items if the desktop is locked. 67 bool DoDefaultAction(); 68 69 // Posts a left click message at this object's center point to the window 70 // containing this object. 71 bool LeftClick(); 72 73 // Posts a right click message at this object's center point to the window 74 // containing this object. 75 bool RightClick(); 76 77 // Focuses this object. Returns whether the object receives focus. Will cause 78 // test failure if the object is not focused. 79 bool Focus(); 80 81 // Selects this object. Returns whether the object is now selected. Will cause 82 // test failure if the object is not selected. 83 bool Select(); 84 85 // Sets the value of the object. Will cause test failure if unsuccessful. 86 bool SetValue(const std::wstring& value); 87 88 // Gets the name of the object and returns true on success. 89 bool GetName(std::wstring* name); 90 91 // Gets the role text of the object and returns true on success. 92 bool GetRoleText(std::wstring* role_text); 93 94 // Gets the value of the object and returns true on success. 95 bool GetValue(std::wstring* value); 96 97 // Gets the state of the object and returns true on success. 98 bool GetState(int* state); 99 100 // Gets the location of the object in screen coordinates and returns true 101 // on success. 102 bool GetLocation(gfx::Rect* location); 103 104 // Gets the location of the object relative to the containing window's 105 // client rect. 106 bool GetLocationInClient(gfx::Rect* location); 107 108 // Gets the parent of the object. May return NULL. 109 AccObject* GetParent(); 110 111 // Gets the children of this object and returns true on success. |objects| 112 // will not be modified unless if the operation is successful. 113 bool GetChildren(RefCountedAccObjectVector* objects); 114 115 // Gets the number of children of this object and returns true on success. 116 bool GetChildCount(int* child_count); 117 118 // Gets an object resulting from the navigation and returns true if the 119 // navigation completed successfully. Even if true, |object| may still 120 // refer to a NULL object if no object was found from the navigation. 121 // |navigation_type| may be any navigation constant, such as NAVDIR_NEXT. 122 // Note: This method uses a deprecated IAccessible method. 123 bool GetFromNavigation(long navigation_type, 124 scoped_refptr<AccObject>* object); 125 126 // Gets the window containing this object and returns true on success. This 127 // method will return false if the object is not contained within a window. 128 bool GetWindow(HWND* window); 129 130 // Gets the class name for the window containing this object and returns true 131 // on success. If this object does not have a window, this will return false. 132 bool GetWindowClassName(std::wstring* class_name); 133 134 // Gets the range of text that is selected in this object. If no text is 135 // selected, |start_offset| and |end_offset| will be set to 0. Returns true 136 // on success. 137 // Requires IAccessible2 support. 138 bool GetSelectionRange(int* start_offset, int* end_offset); 139 140 // Gets the text that is selected in this object. Returns true on success. 141 // Requires IAccessible2 support. 142 bool GetSelectedText(std::wstring* text); 143 144 // Returns whether this object is a simple element. 145 bool IsSimpleElement(); 146 147 // Returns whether the two AccObjects point to the same accessibility object. 148 // |other| can safely be NULL. 149 bool Equals(AccObject* other); 150 151 // Returns a description of this object. 152 std::wstring GetDescription(); 153 154 // Returns a description of this object and it's accessibility tree. This 155 // description will be ended by a newline. 156 std::wstring GetTree(); 157 158 private: 159 friend class base::RefCounted<AccObject>; 160 ~AccObject() {} 161 162 // Creates an AccObject using the given variant, returning NULL on failure. 163 // The variant should be of type |VT_I4| referring to the id of a child of 164 // |object|, or of type |VT_DISPATCH|. This method is useful for converting 165 // the variant returned by many of the IAccessible methods into an AccObject. 166 static AccObject* CreateFromVariant(AccObject* object, 167 const VARIANT& variant); 168 169 // Posts the given mouse button down and up messages at this object's center. 170 // Returns true on success. 171 bool PostMouseClickAtCenter(int button_down, int button_up); 172 173 // Helper method for posting mouse button messages. 174 bool PostMouseButtonMessages(int button_up, int button_down, int x, int y); 175 176 base::win::ScopedComPtr<IAccessible> accessible_; 177 base::win::ScopedVariant child_id_; 178 179 DISALLOW_COPY_AND_ASSIGN(AccObject); 180 }; 181 182 // Finds an accessibility object with properties that match the specified 183 // matching patterns. These patterns can include the standard * and ? wildcards. 184 class AccObjectMatcher { 185 public: 186 // Create a matcher from the given string. |matcher| should include matching 187 // patterns for each property separated by colons. Matching patterns must 188 // be specified from left to right in the following order: 189 // 1) Name 190 // 2) Role Text: A string representation of a Windows object role, which can 191 // be found by using the win32 GetRoleText function. E.g., 192 // ROLE_SYSTEM_ALERT should be represented as 'alert', and 193 // ROLE_SYSTEM_MENUPOPUP should be represented as 'popup menu'. 194 // 3) Value 195 // Matching patterns can be blank, essentially equal to *. 196 // Literal *, ?, and : characters can be escaped with a backslash. 197 AccObjectMatcher(const std::wstring& name = L"", 198 const std::wstring& role_text = L"", 199 const std::wstring& value = L""); 200 201 // Finds the first object which satisfies this matcher and sets as |match|. 202 // This searches the accessibility tree (including |object| itself) of 203 // |object| in a pre-order fasion. If no object is matched, |match| will be 204 // NULL. Returns true if no error occured while trying to find a match. It is 205 // possible to use this method to test for an object's non-existence. 206 bool Find(AccObject* object, scoped_refptr<AccObject>* match) const; 207 208 // Same as above except that it searches within the accessibility tree of the 209 // given window, which must support the IAccessible interface. 210 bool FindInWindow(HWND hwnd, scoped_refptr<AccObject>* match) const; 211 212 // Returns whether |object| satisfies this matcher. 213 bool DoesMatch(AccObject* object) const; 214 215 // Return a description of the matcher, for debugging/logging purposes. 216 std::wstring GetDescription() const; 217 218 private: 219 bool FindHelper(AccObject* object, scoped_refptr<AccObject>* match) const; 220 221 std::wstring name_; 222 std::wstring role_text_; 223 std::wstring value_; 224 }; 225 226 // Observes various accessibility events. 227 class AccEventObserver : public WinEventListener { 228 public: 229 AccEventObserver(); 230 virtual ~AccEventObserver(); 231 232 // Begins watching for a value changed event for an accessibility object that 233 // satisfies |matcher|. Once the event occurs, this observer will stop 234 // watching. 235 void WatchForOneValueChange(const AccObjectMatcher& matcher); 236 237 // Called when the DOM accessibility tree for the page is ready. 238 virtual void OnAccDocLoad(HWND hwnd) = 0; 239 240 // Called when an accessibility object value changes. Only called if the 241 // observer was set to watch for it. 242 virtual void OnAccValueChange(HWND hwnd, AccObject* object, 243 const std::wstring& new_value) = 0; 244 245 // Called when the text caret moves within the given object. This is 246 // triggered when the text selection changes also. 247 virtual void OnTextCaretMoved(HWND hwnd, AccObject* object) = 0; 248 249 // Called when a new menu is shown. 250 virtual void OnMenuPopup(HWND hwnd) = 0; 251 252 private: 253 class EventHandler : public base::RefCounted<EventHandler> { 254 public: 255 explicit EventHandler(AccEventObserver* observer); 256 257 // Examines the given event and invokes the corresponding method of its 258 // observer. 259 void Handle(DWORD event, HWND hwnd, LONG object_id, LONG child_id); 260 261 AccEventObserver* observer_; 262 }; 263 264 // Overriden from WinEventListener. 265 virtual void OnEventReceived(DWORD event, HWND hwnd, LONG object_id, 266 LONG child_id); 267 268 scoped_refptr<EventHandler> event_handler_; 269 bool is_watching_; 270 AccObjectMatcher watching_for_matcher_; 271 WinEventReceiver event_receiver_; 272 }; 273 274 // Finds an AccObject from the given window that satisfied |matcher|. 275 // Will cause test failure in case of error or if no match is found in the 276 // accessibility tree of the specified window. Returns whether the object was 277 // found. 278 bool FindAccObjectInWindow(HWND hwnd, const AccObjectMatcher& matcher, 279 scoped_refptr<AccObject>* object); 280 281 // Writes the accessibility tree for the given window to standard out. Used for 282 // debugging/logging. 283 void DumpAccessibilityTreeForWindow(HWND hwnd); 284 285 // Returns whether the desktop is unlocked. 286 bool IsDesktopUnlocked(); 287 288 // Returns the location of the IAccessible2 COM proxy stub DLL. 289 base::FilePath GetIAccessible2ProxyStubPath(); 290 291 } // namespace chrome_frame_test 292 293 #endif // CHROME_FRAME_TEST_CHROME_FRAME_UI_TEST_UTILS_H_ 294