blob: 680195f09fa8e65cbf6a767a91ff65a75e560f52 [file] [log] [blame]
// 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 <oleacc.h>
#include <string>
#include <vector>
#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<AccObject> {
public:
typedef std::vector<scoped_refptr<AccObject> > 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<AccObject>* 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>;
~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<IAccessible> 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<AccObject>* 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<AccObject>* 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<AccObject>* 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<EventHandler> {
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<EventHandler> 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<AccObject>* 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_