// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_FRAME_TEST_CHROME_FRAME_UI_TEST_UTILS_H_ #define CHROME_FRAME_TEST_CHROME_FRAME_UI_TEST_UTILS_H_ #include #include #include #include "base/file_path.h" #include "base/memory/ref_counted.h" #include "base/win/scoped_comptr.h" #include "base/win/scoped_variant.h" #include "chrome_frame/test/win_event_receiver.h" namespace gfx { class Rect; } namespace chrome_frame_test { // Wrapper for MSAA/IAccessible2 accessibility objects. IAccessible2 is an // open standard which serves as a complement to MSAA and specifies additional // interfaces and methods. Chrome currently supports a subset of this API. // // In MSAA, there are two types of objects. The first, called an object or full // object, has its own IAccessible interface. The second, called a simple // element, does not have its own IAccessible interface and cannot have // children. Simple elements must be referenced by combination of the parent // object and the element's id in MSAA. This class handles this distinction // transparently to the client. class AccObject : public base::RefCounted { public: typedef std::vector > RefCountedAccObjectVector; // Creates an AccObject with an IAccessible and child id. |accessible| must // not be NULL. |child_id| must always be CHILDID_SELF unless this AccObject // is a simple element. AccObject(IAccessible* accessible, int child_id = CHILDID_SELF); // Creates an AccObject corresponding to the given window. May return NULL // if there is not accessible object for the window. The client owns the // created AccObject. static AccObject* CreateFromWindow(HWND hwnd); // Creates an AccObject corresponding to the object that generated a // WinEvent. Returns NULL on failure. static AccObject* CreateFromEvent(HWND hwnd, LONG object_id, LONG child_id); // Creates an AccObject from querying the given IDispatch. May return NULL // if the object does not implement IAccessible. The client owns the created // AccObject. static AccObject* CreateFromDispatch(IDispatch* dispatch); // Creates an AccObject corresponding to the accessible object at the screen // coordinates given. Returns NULL on failure. The client owns the created // AccObject. // Note: This does not work in Chrome. static AccObject* CreateFromPoint(int x, int y); // Performs the default action on this object. Returns whether the action // performed successfully. Will cause test failure if unsuccessful. // Note: This does not work for selecting menu items if the desktop is locked. bool DoDefaultAction(); // Posts a left click message at this object's center point to the window // containing this object. bool LeftClick(); // Posts a right click message at this object's center point to the window // containing this object. bool RightClick(); // Focuses this object. Returns whether the object receives focus. Will cause // test failure if the object is not focused. bool Focus(); // Selects this object. Returns whether the object is now selected. Will cause // test failure if the object is not selected. bool Select(); // Sets the value of the object. Will cause test failure if unsuccessful. bool SetValue(const std::wstring& value); // Gets the name of the object and returns true on success. bool GetName(std::wstring* name); // Gets the role text of the object and returns true on success. bool GetRoleText(std::wstring* role_text); // Gets the value of the object and returns true on success. bool GetValue(std::wstring* value); // Gets the state of the object and returns true on success. bool GetState(int* state); // Gets the location of the object in screen coordinates and returns true // on success. bool GetLocation(gfx::Rect* location); // Gets the location of the object relative to the containing window's // client rect. bool GetLocationInClient(gfx::Rect* location); // Gets the parent of the object. May return NULL. AccObject* GetParent(); // Gets the children of this object and returns true on success. |objects| // will not be modified unless if the operation is successful. bool GetChildren(RefCountedAccObjectVector* objects); // Gets the number of children of this object and returns true on success. bool GetChildCount(int* child_count); // Gets an object resulting from the navigation and returns true if the // navigation completed successfully. Even if true, |object| may still // refer to a NULL object if no object was found from the navigation. // |navigation_type| may be any navigation constant, such as NAVDIR_NEXT. // Note: This method uses a deprecated IAccessible method. bool GetFromNavigation(long navigation_type, scoped_refptr* object); // Gets the window containing this object and returns true on success. This // method will return false if the object is not contained within a window. bool GetWindow(HWND* window); // Gets the class name for the window containing this object and returns true // on success. If this object does not have a window, this will return false. bool GetWindowClassName(std::wstring* class_name); // Gets the range of text that is selected in this object. If no text is // selected, |start_offset| and |end_offset| will be set to 0. Returns true // on success. // Requires IAccessible2 support. bool GetSelectionRange(int* start_offset, int* end_offset); // Gets the text that is selected in this object. Returns true on success. // Requires IAccessible2 support. bool GetSelectedText(std::wstring* text); // Returns whether this object is a simple element. bool IsSimpleElement(); // Returns whether the two AccObjects point to the same accessibility object. // |other| can safely be NULL. bool Equals(AccObject* other); // Returns a description of this object. std::wstring GetDescription(); // Returns a description of this object and it's accessibility tree. This // description will be ended by a newline. std::wstring GetTree(); private: friend class base::RefCounted; ~AccObject() {} // Creates an AccObject using the given variant, returning NULL on failure. // The variant should be of type |VT_I4| referring to the id of a child of // |object|, or of type |VT_DISPATCH|. This method is useful for converting // the variant returned by many of the IAccessible methods into an AccObject. static AccObject* CreateFromVariant(AccObject* object, const VARIANT& variant); // Posts the given mouse button down and up messages at this object's center. // Returns true on success. bool PostMouseClickAtCenter(int button_down, int button_up); // Helper method for posting mouse button messages. bool PostMouseButtonMessages(int button_up, int button_down, int x, int y); base::win::ScopedComPtr accessible_; base::win::ScopedVariant child_id_; DISALLOW_COPY_AND_ASSIGN(AccObject); }; // Finds an accessibility object with properties that match the specified // matching patterns. These patterns can include the standard * and ? wildcards. class AccObjectMatcher { public: // Create a matcher from the given string. |matcher| should include matching // patterns for each property separated by colons. Matching patterns must // be specified from left to right in the following order: // 1) Name // 2) Role Text: A string representation of a Windows object role, which can // be found by using the win32 GetRoleText function. E.g., // ROLE_SYSTEM_ALERT should be represented as 'alert', and // ROLE_SYSTEM_MENUPOPUP should be represented as 'popup menu'. // 3) Value // Matching patterns can be blank, essentially equal to *. // Literal *, ?, and : characters can be escaped with a backslash. AccObjectMatcher(const std::wstring& name = L"", const std::wstring& role_text = L"", const std::wstring& value = L""); // Finds the first object which satisfies this matcher and sets as |match|. // This searches the accessibility tree (including |object| itself) of // |object| in a pre-order fasion. If no object is matched, |match| will be // NULL. Returns true if no error occured while trying to find a match. It is // possible to use this method to test for an object's non-existence. bool Find(AccObject* object, scoped_refptr* match) const; // Same as above except that it searches within the accessibility tree of the // given window, which must support the IAccessible interface. bool FindInWindow(HWND hwnd, scoped_refptr* match) const; // Returns whether |object| satisfies this matcher. bool DoesMatch(AccObject* object) const; // Return a description of the matcher, for debugging/logging purposes. std::wstring GetDescription() const; private: bool FindHelper(AccObject* object, scoped_refptr* match) const; std::wstring name_; std::wstring role_text_; std::wstring value_; }; // Observes various accessibility events. class AccEventObserver : public WinEventListener { public: AccEventObserver(); virtual ~AccEventObserver(); // Begins watching for a value changed event for an accessibility object that // satisfies |matcher|. Once the event occurs, this observer will stop // watching. void WatchForOneValueChange(const AccObjectMatcher& matcher); // Called when the DOM accessibility tree for the page is ready. virtual void OnAccDocLoad(HWND hwnd) = 0; // Called when an accessibility object value changes. Only called if the // observer was set to watch for it. virtual void OnAccValueChange(HWND hwnd, AccObject* object, const std::wstring& new_value) = 0; // Called when the text caret moves within the given object. This is // triggered when the text selection changes also. virtual void OnTextCaretMoved(HWND hwnd, AccObject* object) = 0; // Called when a new menu is shown. virtual void OnMenuPopup(HWND hwnd) = 0; private: class EventHandler : public base::RefCounted { public: explicit EventHandler(AccEventObserver* observer); // Examines the given event and invokes the corresponding method of its // observer. void Handle(DWORD event, HWND hwnd, LONG object_id, LONG child_id); AccEventObserver* observer_; }; // Overriden from WinEventListener. virtual void OnEventReceived(DWORD event, HWND hwnd, LONG object_id, LONG child_id); scoped_refptr event_handler_; bool is_watching_; AccObjectMatcher watching_for_matcher_; WinEventReceiver event_receiver_; }; // Finds an AccObject from the given window that satisfied |matcher|. // Will cause test failure in case of error or if no match is found in the // accessibility tree of the specified window. Returns whether the object was // found. bool FindAccObjectInWindow(HWND hwnd, const AccObjectMatcher& matcher, scoped_refptr* object); // Writes the accessibility tree for the given window to standard out. Used for // debugging/logging. void DumpAccessibilityTreeForWindow(HWND hwnd); // Returns whether the desktop is unlocked. bool IsDesktopUnlocked(); // Returns the location of the IAccessible2 COM proxy stub DLL. FilePath GetIAccessible2ProxyStubPath(); } // namespace chrome_frame_test #endif // CHROME_FRAME_TEST_CHROME_FRAME_UI_TEST_UTILS_H_