tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

LazyInstantiator.h (6659B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_a11y_LazyInstantiator_h
      8 #define mozilla_a11y_LazyInstantiator_h
      9 
     10 #include "IUnknownImpl.h"
     11 #include "mozilla/Maybe.h"
     12 #include "mozilla/RefPtr.h"
     13 #include "nsString.h"
     14 
     15 #include <oleacc.h>
     16 #include <uiautomation.h>
     17 
     18 class nsIFile;
     19 
     20 namespace mozilla {
     21 namespace a11y {
     22 
     23 class MsaaRootAccessible;
     24 
     25 /**
     26 * LazyInstantiator is an IAccessible that initially acts as a placeholder.
     27 * The a11y service is not actually started until two conditions are met:
     28 *
     29 * (1) A method is called on the LazyInstantiator that would require a11y
     30 *     services in order to fulfill; and
     31 * (2) LazyInstantiator::ShouldInstantiate returns true.
     32 */
     33 class LazyInstantiator final : public IAccessible,
     34                               public IServiceProvider,
     35                               public IRawElementProviderSimple {
     36 public:
     37  [[nodiscard]] static already_AddRefed<IAccessible> GetRootAccessible(
     38      HWND aHwnd);
     39  [[nodiscard]] static already_AddRefed<IRawElementProviderSimple> GetRootUia(
     40      HWND aHwnd);
     41  static void EnableBlindAggregation(HWND aHwnd);
     42 
     43  // IUnknown
     44  STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override;
     45  STDMETHODIMP_(ULONG) AddRef() override;
     46  STDMETHODIMP_(ULONG) Release() override;
     47 
     48  // IDispatch
     49  STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) override;
     50  STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid,
     51                           ITypeInfo** ppTInfo) override;
     52  STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
     53                             LCID lcid, DISPID* rgDispId) override;
     54  STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
     55                      DISPPARAMS* pDispParams, VARIANT* pVarResult,
     56                      EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
     57 
     58  // IAccessible
     59  STDMETHODIMP get_accParent(IDispatch** ppdispParent) override;
     60  STDMETHODIMP get_accChildCount(long* pcountChildren) override;
     61  STDMETHODIMP get_accChild(VARIANT varChild, IDispatch** ppdispChild) override;
     62  STDMETHODIMP get_accName(VARIANT varChild, BSTR* pszName) override;
     63  STDMETHODIMP get_accValue(VARIANT varChild, BSTR* pszValue) override;
     64  STDMETHODIMP get_accDescription(VARIANT varChild,
     65                                  BSTR* pszDescription) override;
     66  STDMETHODIMP get_accRole(VARIANT varChild, VARIANT* pvarRole) override;
     67  STDMETHODIMP get_accState(VARIANT varChild, VARIANT* pvarState) override;
     68  STDMETHODIMP get_accHelp(VARIANT varChild, BSTR* pszHelp) override;
     69  STDMETHODIMP get_accHelpTopic(BSTR* pszHelpFile, VARIANT varChild,
     70                                long* pidTopic) override;
     71  STDMETHODIMP get_accKeyboardShortcut(VARIANT varChild,
     72                                       BSTR* pszKeyboardShortcut) override;
     73  STDMETHODIMP get_accFocus(VARIANT* pvarChild) override;
     74  STDMETHODIMP get_accSelection(VARIANT* pvarChildren) override;
     75  STDMETHODIMP get_accDefaultAction(VARIANT varChild,
     76                                    BSTR* pszDefaultAction) override;
     77  STDMETHODIMP accSelect(long flagsSelect, VARIANT varChild) override;
     78  STDMETHODIMP accLocation(long* pxLeft, long* pyTop, long* pcxWidth,
     79                           long* pcyHeight, VARIANT varChild) override;
     80  STDMETHODIMP accNavigate(long navDir, VARIANT varStart,
     81                           VARIANT* pvarEndUpAt) override;
     82  STDMETHODIMP accHitTest(long xLeft, long yTop, VARIANT* pvarChild) override;
     83  STDMETHODIMP accDoDefaultAction(VARIANT varChild) override;
     84  STDMETHODIMP put_accName(VARIANT varChild, BSTR szName) override;
     85  STDMETHODIMP put_accValue(VARIANT varChild, BSTR szValue) override;
     86 
     87  // IServiceProvider
     88  STDMETHODIMP QueryService(REFGUID aServiceId, REFIID aServiceIid,
     89                            void** aOutInterface) override;
     90 
     91  // IRawElementProviderSimple
     92  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ProviderOptions(
     93      /* [retval][out] */ __RPC__out enum ProviderOptions* aProviderOptions);
     94 
     95  virtual HRESULT STDMETHODCALLTYPE GetPatternProvider(
     96      /* [in] */ PATTERNID aPatternId,
     97      /* [retval][out] */ __RPC__deref_out_opt IUnknown** aPatternProvider);
     98 
     99  virtual HRESULT STDMETHODCALLTYPE GetPropertyValue(
    100      /* [in] */ PROPERTYID aPropertyId,
    101      /* [retval][out] */ __RPC__out VARIANT* aPropertyValue);
    102 
    103  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HostRawElementProvider(
    104      /* [retval][out] */ __RPC__deref_out_opt IRawElementProviderSimple**
    105          aRawElmProvider);
    106 
    107  /**
    108   * We cache the result of UIA detection because it could be expensive if a
    109   * client repeatedly queries us. This function is called to reset that cache
    110   * when one of our windows comes to the foreground. If there is a new UIA
    111   * client that isn't blocked, instantiation will subsequently be allowed. The
    112   * hope is that a user will probably need to switch apps in order to start a
    113   * new client.
    114   */
    115  static void ResetUiaDetectionCache() { sShouldBlockUia = Nothing(); }
    116 
    117 private:
    118  explicit LazyInstantiator(HWND aHwnd);
    119  ~LazyInstantiator();
    120 
    121  bool IsBlockedInjection();
    122  bool ShouldInstantiate(const DWORD aClientPid);
    123  bool ShouldInstantiate();
    124 
    125  DWORD GetRemoteMsaaClientPid();
    126 
    127  /**
    128   * @return S_OK if we have a valid mRealRoot to invoke methods on
    129   */
    130  HRESULT MaybeResolveRoot();
    131 
    132  /**
    133   * @return S_OK if we have a valid mWeakDispatch to invoke methods on
    134   */
    135  HRESULT ResolveDispatch();
    136 
    137  MsaaRootAccessible* ResolveMsaaRoot();
    138  void TransplantRefCnt();
    139  void ClearProp();
    140 
    141  template <class T>
    142  static already_AddRefed<T> GetRoot(HWND aHwnd);
    143 
    144 private:
    145  mozilla::a11y::AutoRefCnt mRefCnt;
    146  HWND mHwnd;
    147  bool mAllowBlindAggregation;
    148  RefPtr<IUnknown> mRealRootUnk;
    149  RefPtr<IUnknown> mStdDispatch;
    150  /**
    151   * mWeakMsaaRoot, mWeakAccessible and mWeakDispatch are weak because they
    152   * are interfaces that come from objects that we aggregate. Aggregated object
    153   * interfaces share refcount methods with ours, so if we were to hold strong
    154   * references to them, we would be holding strong references to ourselves,
    155   * creating a cycle.
    156   */
    157  MsaaRootAccessible* mWeakMsaaRoot;
    158  IAccessible* mWeakAccessible;
    159  IDispatch* mWeakDispatch;
    160  IRawElementProviderSimple* mWeakUia;
    161  static Maybe<bool> sShouldBlockUia;
    162 };
    163 
    164 }  // namespace a11y
    165 }  // namespace mozilla
    166 
    167 #endif  // mozilla_a11y_LazyInstantiator_h