Bug 1380471: Move follow-up initialization for emulated windows into a callback invoked by the emulated window's WM_CREATE handler; r=yzen
☠☠ backed out by 2a4effa27df4 ☠ ☠
authorAaron Klotz <aklotz@mozilla.com>
Wed, 12 Jul 2017 18:01:43 -0600
changeset 608667 7ec72cbf67b6e612ef7eff1a542ea99ac2539b5d
parent 608666 f1f96310ee1f29b8aaa151bb291dc470b99571e9
child 608668 4f2374156926221bb6860d439e3b4292b4da8069
push id68368
push userbmo:a.beingessner@gmail.com
push dateFri, 14 Jul 2017 01:37:37 +0000
reviewersyzen
bugs1380471
milestone56.0a1
Bug 1380471: Move follow-up initialization for emulated windows into a callback invoked by the emulated window's WM_CREATE handler; r=yzen
accessible/ipc/DocAccessibleParent.cpp
accessible/windows/msaa/DocAccessibleWrap.cpp
accessible/windows/msaa/nsWinUtils.cpp
accessible/windows/msaa/nsWinUtils.h
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -618,36 +618,41 @@ DocAccessibleParent::MaybeInitWindowEmul
     nsIntRect rootRect = rootDocument->Bounds();
     rect.x = rootRect.x - rect.x;
     rect.y -= rootRect.y;
 
     auto tab = static_cast<dom::TabParent*>(Manager());
     tab->GetDocShellIsActive(&isActive);
   }
 
-  IAccessibleHolder hWndAccHolder;
-  HWND parentWnd = reinterpret_cast<HWND>(rootDocument->GetNativeWindow());
-  HWND hWnd = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
-                                             parentWnd, rect.x, rect.y,
-                                             rect.width, rect.height,
-                                             isActive);
-  if (hWnd) {
-    // Attach accessible document to the emulated native window
-    ::SetPropW(hWnd, kPropNameDocAccParent, (HANDLE)this);
-    SetEmulatedWindowHandle(hWnd);
+  nsWinUtils::NativeWindowCreateProc onCreate([this](HWND aHwnd) -> void {
+    IAccessibleHolder hWndAccHolder;
+
+    ::SetPropW(aHwnd, kPropNameDocAccParent, reinterpret_cast<HANDLE>(this));
+
+    SetEmulatedWindowHandle(aHwnd);
+
     IAccessible* rawHWNDAcc = nullptr;
-    if (SUCCEEDED(::AccessibleObjectFromWindow(hWnd, OBJID_WINDOW,
+    if (SUCCEEDED(::AccessibleObjectFromWindow(aHwnd, OBJID_WINDOW,
                                                IID_IAccessible,
                                                (void**)&rawHWNDAcc))) {
       hWndAccHolder.Set(IAccessibleHolder::COMPtrType(rawHWNDAcc));
     }
-  }
+
+    Unused << SendEmulatedWindow(reinterpret_cast<uintptr_t>(mEmulatedWindowHandle),
+                                 hWndAccHolder);
+  });
 
-  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.
  */
 void
 DocAccessibleParent::SendParentCOMProxy()
 {
--- a/accessible/windows/msaa/DocAccessibleWrap.cpp
+++ b/accessible/windows/msaa/DocAccessibleWrap.cpp
@@ -158,22 +158,24 @@ DocAccessibleWrap::DoInitialUpdate()
         rect.x = rootRect.x - rect.x;
         rect.y -= rootRect.y;
 
         nsCOMPtr<nsISupports> container = mDocumentNode->GetContainer();
         nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
         docShell->GetIsActive(&isActive);
       }
 
+      nsWinUtils::NativeWindowCreateProc onCreate([this](HWND aHwnd) -> void {
+        ::SetPropW(aHwnd, kPropNameDocAcc, reinterpret_cast<HANDLE>(this));
+      });
+
       HWND parentWnd = reinterpret_cast<HWND>(rootDocument->GetNativeWindow());
       mHWND = nsWinUtils::CreateNativeWindow(kClassNameTabContent, parentWnd,
                                              rect.x, rect.y,
-                                             rect.width, rect.height, isActive);
-
-      ::SetPropW(static_cast<HWND>(mHWND), kPropNameDocAcc, (HANDLE)this);
-
+                                             rect.width, rect.height, isActive,
+                                             &onCreate);
     } else {
       DocAccessible* parentDocument = ParentDocument();
       if (parentDocument)
         mHWND = parentDocument->GetNativeWindow();
     }
   }
 }
--- a/accessible/windows/msaa/nsWinUtils.cpp
+++ b/accessible/windows/msaa/nsWinUtils.cpp
@@ -105,31 +105,27 @@ nsWinUtils::RegisterNativeWindow(LPCWSTR
   wc.lpszMenuName = nullptr;
   wc.lpszClassName = aWindowClass;
   ::RegisterClassW(&wc);
 }
 
 HWND
 nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd,
                                int aX, int aY, int aWidth, int aHeight,
-                               bool aIsActive)
+                               bool aIsActive,
+                               NativeWindowCreateProc* aOnCreateProc)
 {
-  HWND hwnd = ::CreateWindowExW(WS_EX_TRANSPARENT, aWindowClass,
-                                L"NetscapeDispatchWnd",
-                                WS_CHILD | (aIsActive ? WS_VISIBLE : 0),
-                                aX, aY, aWidth, aHeight,
-                                aParentWnd,
-                                nullptr,
-                                GetModuleHandle(nullptr),
-                                nullptr);
-  if (hwnd) {
-    // Mark this window so that ipc related code can identify it.
-    ::SetPropW(hwnd, kPropNameTabContent, (HANDLE)1);
-  }
-  return hwnd;
+  return ::CreateWindowExW(WS_EX_TRANSPARENT, aWindowClass,
+                           L"NetscapeDispatchWnd",
+                           WS_CHILD | (aIsActive ? WS_VISIBLE : 0),
+                           aX, aY, aWidth, aHeight,
+                           aParentWnd,
+                           nullptr,
+                           GetModuleHandle(nullptr),
+                           aOnCreateProc);
 }
 
 void
 nsWinUtils::ShowNativeWindow(HWND aWnd)
 {
   ::ShowWindow(aWnd, SW_SHOW);
 }
 
@@ -144,16 +140,31 @@ nsWinUtils::HideNativeWindow(HWND aWnd)
 LRESULT CALLBACK
 WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
   // Note, this window's message handling should not invoke any call that
   // may result in a cross-process ipc call. Doing so may violate RPC
   // message semantics.
 
   switch (msg) {
+    case WM_CREATE:
+    {
+      // Mark this window so that ipc related code can identify it.
+      ::SetPropW(hWnd, kPropNameTabContent, reinterpret_cast<HANDLE>(1));
+
+      auto createStruct = reinterpret_cast<CREATESTRUCT*>(lParam);
+      auto createProc = reinterpret_cast<nsWinUtils::NativeWindowCreateProc*>(
+        createStruct->lpCreateParams);
+
+      if (createProc && *createProc) {
+        (*createProc)(hWnd);
+      }
+
+      return 0;
+    }
     case WM_GETOBJECT:
     {
       // Do explicit casting to make it working on 64bit systems (see bug 649236
       // for details).
       int32_t objId = static_cast<DWORD>(lParam);
       if (objId == OBJID_CLIENT) {
         IAccessible* msaaAccessible = nullptr;
         DocAccessible* document =
--- a/accessible/windows/msaa/nsWinUtils.h
+++ b/accessible/windows/msaa/nsWinUtils.h
@@ -3,16 +3,17 @@
  */
 /* 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 nsWinUtils_h_
 #define nsWinUtils_h_
 
+#include <functional>
 #include <windows.h>
 
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsCOMPtr.h"
 
 class nsIContent;
 
 namespace mozilla {
@@ -52,22 +53,40 @@ public:
    */
   static bool IsWindowEmulationStarted() { return sWindowEmulationStarted; }
 
   /**
    * Helper to register window class.
    */
   static void RegisterNativeWindow(LPCWSTR aWindowClass);
 
+  typedef std::function<void(HWND)> NativeWindowCreateProc;
+
   /**
    * Helper to create a window.
+   *
+   * NB: If additional setup needs to be done once the window has been created,
+   *     you should do so via aOnCreateProc. Hooks will fire during the
+   *     CreateNativeWindow call, thus triggering events in the AT.
+   *     Using aOnCreateProc guarantees that your additional initialization will
+   *     have completed prior to the AT receiving window creation events.
+   *
+   *     For example:
+   *
+   *     nsWinUtils::NativeWindowCreateProc onCreate([](HWND aHwnd) -> void {
+   *       DoSomeAwesomeInitializationStuff(aHwnd);
+   *       DoMoreAwesomeInitializationStuff(aHwnd);
+   *     });
+   *     HWND hwnd = nsWinUtils::CreateNativeWindow(..., &onCreate);
+   *     // Doing further initialization work to hwnd on this line is too late!
    */
   static HWND CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd,
                                  int aX, int aY, int aWidth, int aHeight,
-                                 bool aIsActive);
+                                 bool aIsActive,
+                                 NativeWindowCreateProc* aOnCreateProc = nullptr);
 
   /**
    * Helper to show window.
    */
   static void ShowNativeWindow(HWND aWnd);
 
   /**
    * Helper to hide window.