/**
 * @param aCOMProxy COM Proxy to the document in the content process.
 */
void
DocAccessibleParent::SendParentCOMProxy()
{
  // Make sure that we're not racing with a tab shutdown
  auto tab = static_cast<dom::TabParent*>(Manager());
  MOZ_ASSERT(tab);
  if (tab->IsDestroyed()) {
    return;
  }

  Accessible* outerDoc = OuterDocOfRemoteBrowser();
  if (!outerDoc) {
    return;
  }

  IAccessible* rawNative = nullptr;
  outerDoc->GetNativeInterface((void**) &rawNative);
  MOZ_ASSERT(rawNative);

  IAccessibleHolder::COMPtrType ptr(rawNative);
  IAccessibleHolder holder(Move(ptr));
  if (!PDocAccessibleParent::SendParentCOMProxy(holder)) {
    return;
  }

#if defined(MOZ_CONTENT_SANDBOX)
  mParentProxyStream = Move(holder.GetPreservedStream());
#endif // defined(MOZ_CONTENT_SANDBOX)
}
void
DocAccessibleParent::MaybeInitWindowEmulation()
{
  if (!nsWinUtils::IsWindowEmulationStarted()) {
    return;
  }

  // XXX get the bounds from the tabParent instead of poking at accessibles
  // which might not exist yet.
  Accessible* outerDoc = OuterDocOfRemoteBrowser();
  if (!outerDoc) {
    return;
  }

  RootAccessible* rootDocument = outerDoc->RootAccessible();
  MOZ_ASSERT(rootDocument);

  bool isActive = true;
  nsIntRect rect(CW_USEDEFAULT, CW_USEDEFAULT, 0, 0);
  if (Compatibility::IsDolphin()) {
    rect = Bounds();
    nsIntRect rootRect = rootDocument->Bounds();
    rect.x = rootRect.x - rect.x;
    rect.y -= rootRect.y;

    auto tab = static_cast<dom::TabParent*>(Manager());
    tab->GetDocShellIsActive(&isActive);
  }

  nsWinUtils::NativeWindowCreateProc onCreate([this](HWND aHwnd) -> void {
    IAccessibleHolder hWndAccHolder;

    ::SetPropW(aHwnd, kPropNameDocAccParent, reinterpret_cast<HANDLE>(this));

    SetEmulatedWindowHandle(aHwnd);

    IAccessible* rawHWNDAcc = nullptr;
    if (SUCCEEDED(::AccessibleObjectFromWindow(aHwnd, OBJID_WINDOW,
                                               IID_IAccessible,
                                               (void**)&rawHWNDAcc))) {
      hWndAccHolder.Set(IAccessibleHolder::COMPtrType(rawHWNDAcc));
    }

    Unused << SendEmulatedWindow(reinterpret_cast<uintptr_t>(mEmulatedWindowHandle),
                                 hWndAccHolder);
  });

  HWND parentWnd = reinterpret_cast<HWND>(rootDocument->GetNativeWindow());
  DebugOnly<HWND> hWnd = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
                                                        parentWnd,
                                                        rect.x, rect.y,
                                                        rect.width, rect.height,
                                                        isActive, &onCreate);
  MOZ_ASSERT(hWnd);
}
/**
 * @param aCOMProxy COM Proxy to the document in the content process.
 * @param aParentCOMProxy COM Proxy to the OuterDocAccessible that is
 *        the parent of the document. The content process will use this
 *        proxy when traversing up across the content/chrome boundary.
 */
bool
DocAccessibleParent::RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
                                  IAccessibleHolder* aParentCOMProxy)
{
  RefPtr<IAccessible> ptr(aCOMProxy.Get());
  SetCOMInterface(ptr);

  Accessible* outerDoc = OuterDocOfRemoteBrowser();
  IAccessible* rawNative = nullptr;
  if (outerDoc) {
    outerDoc->GetNativeInterface((void**) &rawNative);
  }

  aParentCOMProxy->Set(IAccessibleHolder::COMPtrType(rawNative));
  return true;
}
/**
 * @param aCOMProxy COM Proxy to the document in the content process.
 */
void
DocAccessibleParent::SendParentCOMProxy()
{
  // Make sure that we're not racing with a tab shutdown
  auto tab = static_cast<dom::TabParent*>(Manager());
  MOZ_ASSERT(tab);
  if (tab->IsDestroyed()) {
    return;
  }

  Accessible* outerDoc = OuterDocOfRemoteBrowser();
  if (!outerDoc) {
    return;
  }

  IAccessible* rawNative = nullptr;
  outerDoc->GetNativeInterface((void**) &rawNative);
  MOZ_ASSERT(rawNative);

  IAccessibleHolder::COMPtrType ptr(rawNative);
  IAccessibleHolder holder(Move(ptr));
  Unused << PDocAccessibleParent::SendParentCOMProxy(holder);
}