summaryrefslogtreecommitdiffstats
path: root/accessible/ipc/win/HandlerProvider.h
blob: f517a0f9919c142053e0ade89b4e7d03d813d73a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_a11y_HandlerProvider_h
#define mozilla_a11y_HandlerProvider_h

#include "mozilla/a11y/AccessibleHandler.h"
#include "mozilla/a11y/HandlerDataCleanup.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Atomics.h"
#include "mozilla/mscom/IHandlerProvider.h"
#include "mozilla/mscom/Ptr.h"
#include "mozilla/mscom/StructStream.h"
#include "mozilla/Mutex.h"
#include "mozilla/UniquePtr.h"
#include "HandlerData.h"

struct NEWEST_IA2_INTERFACE;

namespace mozilla {

namespace mscom {

class StructToStream;

}  // namespace mscom

namespace a11y {

class HandlerProvider final : public IGeckoBackChannel,
                              public mscom::IHandlerProvider {
 public:
  HandlerProvider(REFIID aIid, mscom::InterceptorTargetPtr<IUnknown> aTarget);

  // IUnknown
  STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
  STDMETHODIMP_(ULONG) AddRef() override;
  STDMETHODIMP_(ULONG) Release() override;

  // IHandlerProvider
  STDMETHODIMP GetHandler(NotNull<CLSID*> aHandlerClsid) override;
  STDMETHODIMP GetHandlerPayloadSize(NotNull<mscom::IInterceptor*> aInterceptor,
                                     NotNull<DWORD*> aOutPayloadSize) override;
  STDMETHODIMP WriteHandlerPayload(NotNull<mscom::IInterceptor*> aInterceptor,
                                   NotNull<IStream*> aStream) override;
  STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override;
  STDMETHODIMP DisconnectHandlerRemotes() override;
  STDMETHODIMP IsInterfaceMaybeSupported(REFIID aIid) override;
  STDMETHODIMP_(REFIID)
  GetEffectiveOutParamIid(REFIID aCallIid, ULONG aCallMethod) override;
  STDMETHODIMP NewInstance(
      REFIID aIid, mscom::InterceptorTargetPtr<IUnknown> aTarget,
      NotNull<mscom::IHandlerProvider**> aOutNewPayload) override;

  // IGeckoBackChannel
  STDMETHODIMP put_HandlerControl(long aPid, IHandlerControl* aCtrl) override;
  STDMETHODIMP Refresh(DynamicIA2Data* aOutData) override;
  STDMETHODIMP get_AllTextInfo(BSTR* aText, IAccessibleHyperlink*** aHyperlinks,
                               long* aNHyperlinks, IA2TextSegment** aAttribRuns,
                               long* aNAttribRuns) override;
  STDMETHODIMP get_RelationsInfo(IARelationData** aRelations,
                                 long* aNRelations) override;
  STDMETHODIMP get_AllChildren(AccChildData** aChildren,
                               ULONG* aNChildren) override;

 private:
  ~HandlerProvider() = default;

  void SetHandlerControlOnMainThread(
      DWORD aPid, mscom::ProxyUniquePtr<IHandlerControl> aCtrl);
  void GetAndSerializePayload(const MutexAutoLock&,
                              NotNull<mscom::IInterceptor*> aInterceptor);
  void BuildStaticIA2Data(NotNull<mscom::IInterceptor*> aInterceptor,
                          StaticIA2Data* aOutData);
  /**
   * Pass true for aMarshaledByCom if this struct is being directly marshaled as
   * an out parameter of a COM method, currently only
   * IGeckoBackChannel::Refresh.
   * When aMarshaledByCom is false, this means the struct is being marshaled
   * by RPC encoding functions. This means we must allocate memory differently,
   * even though we're using this as part of a COM handler payload.
   */
  void BuildDynamicIA2Data(DynamicIA2Data* aOutIA2Data,
                           bool aMarshaledByCom = false);
  void BuildInitialIA2Data(NotNull<mscom::IInterceptor*> aInterceptor,
                           StaticIA2Data* aOutStaticData,
                           DynamicIA2Data* aOutDynamicData);
  bool IsTargetInterfaceCacheable();

  /**
   * Build the payload for later marshaling.
   * This is intended to be used during a bulk fetch operation and must only be
   * called from the main thread.
   */
  void PrebuildPayload(NotNull<mscom::IInterceptor*> aInterceptor);

  // Replace a raw object from the main thread with a wrapped, intercepted
  // object suitable for calling from the MTA.
  // The reference to the original object is adopted; i.e. you should not
  // separately release it.
  // This is intended for objects returned from method calls on the main thread.
  template <typename Interface>
  HRESULT ToWrappedObject(Interface** aObj);
  void GetAllTextInfoMainThread(BSTR* aText,
                                IAccessibleHyperlink*** aHyperlinks,
                                long* aNHyperlinks,
                                IA2TextSegment** aAttribRuns,
                                long* aNAttribRuns, HRESULT* result);
  void GetRelationsInfoMainThread(IARelationData** aRelations,
                                  long* aNRelations, HRESULT* result);
  void GetAllChildrenMainThread(AccChildData** aChildren, ULONG* aNChildren,
                                HRESULT* result);

  Atomic<uint32_t> mRefCnt;
  Mutex mMutex MOZ_UNANNOTATED;  // Protects mSerializer
  const IID mTargetUnkIid;
  mscom::InterceptorTargetPtr<IUnknown>
      mTargetUnk;  // Constant, main thread only
  UniquePtr<mscom::StructToStream> mSerializer;
  RefPtr<IUnknown> mFastMarshalUnk;

  struct IA2PayloadDeleter {
    void operator()(IA2Payload* aPayload) {
      // When CoMarshalInterface writes interfaces out to a stream, it AddRefs.
      // Therefore, we must release our references after this.
      ReleaseStaticIA2DataInterfaces(aPayload->mStaticData);
      CleanupDynamicIA2Data(aPayload->mDynamicData);
      delete aPayload;
    }
  };
  using IA2PayloadPtr = UniquePtr<IA2Payload, IA2PayloadDeleter>;

  // Used when the payload is built prior to marshaling the object by a bulk
  // fetch operation. See prebuildPayload().
  IA2PayloadPtr mPayload;
  Mutex mPayloadMutex MOZ_UNANNOTATED;  // Protects mPayload
};

}  // namespace a11y
}  // namespace mozilla

#endif  // mozilla_a11y_HandlerProvider_h