Home | History | Annotate | Download | only in test
      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