Bug 671550 - provide correct parent HWND for content process window, r=jones.chris.g, davidb
authorAlexander Surkov <surkov.alexander@gmail.com>
Fri, 22 Jul 2011 09:49:35 +0900
changeset 73212 f1d496722775cb34a226bb171c1a258bedda0d5c
parent 73211 e9b6850cc32492bec659519833fb2f209b6b0f85
child 73213 b2c429bb9f3f9f7b00e5e17a009bc3c137bd6f36
push idunknown
push userunknown
push dateunknown
reviewersjones
bugs671550
milestone8.0a1
Bug 671550 - provide correct parent HWND for content process window, r=jones.chris.g, davidb
accessible/src/base/nsAccDocManager.h
accessible/src/base/nsCoreUtils.cpp
accessible/src/base/nsCoreUtils.h
accessible/src/msaa/Makefile.in
accessible/src/msaa/nsAccessibleWrap.cpp
accessible/src/msaa/nsDocAccessibleWrap.cpp
accessible/src/msaa/nsRootAccessibleWrap.cpp
accessible/src/msaa/nsWinUtils.cpp
accessible/src/msaa/nsWinUtils.h
dom/ipc/PBrowser.ipdl
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
ipc/glue/IPCMessageUtils.h
--- a/accessible/src/base/nsAccDocManager.h
+++ b/accessible/src/base/nsAccDocManager.h
@@ -201,16 +201,29 @@ private:
 #define NS_LOG_ACCDOC_TYPE(aDocument)                                          \
   if (aDocument->IsActive()) {                                                 \
     PRBool isContent = nsCoreUtils::IsContentDocument(aDocument);              \
     printf("%s document", (isContent ? "content" : "chrome"));                 \
   } else {                                                                     \
     printf("document type: [failed]");                                         \
   }
 
+#define NS_LOG_ACCDOC_DOCSHELLTREE(aDocument)                                  \
+  if (aDocument->IsActive()) {                                                 \
+    nsCOMPtr<nsISupports> container = aDocument->GetContainer();               \
+    nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));      \
+    nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;                              \
+    treeItem->GetParent(getter_AddRefs(parentTreeItem));                       \
+    nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;                                \
+    treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));                   \
+    printf("docshell hierarchy, parent: %p, root: %p, is tab document: %s;",   \
+           parentTreeItem, rootTreeItem,                                       \
+           (nsCoreUtils::IsTabDocument(aDocument) ? "yes" : "no"));            \
+  }
+
 #define NS_LOG_ACCDOC_SHELLSTATE(aDocument)                                    \
   nsCAutoString docShellBusy;                                                  \
   nsCOMPtr<nsISupports> container = aDocument->GetContainer();                 \
   if (container) {                                                             \
     nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);             \
     PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE;                         \
     docShell->GetBusyFlags(&busyFlags);                                        \
     if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE)                             \
@@ -347,16 +360,18 @@ private:
     printf("\n    ");                                                          \
     if (aDocument) {                                                           \
       NS_LOG_ACCDOC_URI(aDocument)                                             \
       printf("\n    ");                                                        \
       NS_LOG_ACCDOC_SHELLSTATE(aDocument)                                      \
       printf("; ");                                                            \
       NS_LOG_ACCDOC_TYPE(aDocument)                                            \
       printf("\n    ");                                                        \
+      NS_LOG_ACCDOC_DOCSHELLTREE(aDocument)                                    \
+      printf("\n    ");                                                        \
       NS_LOG_ACCDOC_DOCSTATES(aDocument)                                       \
       printf("\n    ");                                                        \
       NS_LOG_ACCDOC_DOCPRESSHELL(aDocument)                                    \
       printf("\n    ");                                                        \
       NS_LOG_ACCDOC_DOCLOADGROUP(aDocument)                                    \
       printf(", ");                                                            \
       NS_LOG_ACCDOC_DOCPARENT(aDocument)                                       \
       printf("\n");                                                            \
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -475,16 +475,36 @@ nsCoreUtils::IsContentDocument(nsIDocume
     do_QueryInterface(container);
   NS_ASSERTION(docShellTreeItem, "No document shell tree item for document!");
 
   PRInt32 contentType;
   docShellTreeItem->GetItemType(&contentType);
   return (contentType == nsIDocShellTreeItem::typeContent);
 }
 
+bool
+nsCoreUtils::IsTabDocument(nsIDocument* aDocumentNode)
+{
+  nsCOMPtr<nsISupports> container = aDocumentNode->GetContainer();
+  nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
+
+  nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
+  treeItem->GetParent(getter_AddRefs(parentTreeItem));
+
+  // Tab document running in own process doesn't have parent.
+  if (XRE_GetProcessType() == GeckoProcessType_Content)
+    return !parentTreeItem;
+
+  // Parent of docshell for tab document running in chrome process is root.
+  nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
+  treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
+
+  return parentTreeItem == rootTreeItem;
+}
+
 PRBool
 nsCoreUtils::IsErrorPage(nsIDocument *aDocument)
 {
   nsIURI *uri = aDocument->GetDocumentURI();
   PRBool isAboutScheme = PR_FALSE;
   uri->SchemeIs("about", &isAboutScheme);
   if (!isAboutScheme)
     return PR_FALSE;
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -229,16 +229,21 @@ public:
   static PRBool IsRootDocument(nsIDocument *aDocument);
 
   /**
    * Return true if the given document is content document (not chrome).
    */
   static PRBool IsContentDocument(nsIDocument *aDocument);
 
   /**
+   * Return true if the given document node is for tab document accessible.
+   */
+  static bool IsTabDocument(nsIDocument* aDocumentNode);
+
+  /**
    * Return true if the given document is an error page.
    */
   static PRBool IsErrorPage(nsIDocument *aDocument);
 
   /**
    * Retrun true if the type of given frame equals to the given frame type.
    *
    * @param aFrame  the frame
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -102,17 +102,20 @@ EXPORTS = \
   CAccessibleTable.h \
   CAccessibleTableCell.h \
   CAccessibleValue.h \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../base \
   -I$(srcdir)/../html \
   -I$(srcdir)/../xul \
+  -I$(srcdir)/../../../content/base/src \
+  -I$(srcdir)/../../../content/events/src \
   $(NULL)
-
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -199,17 +199,17 @@ STDMETHODIMP nsAccessibleWrap::get_accPa
     return E_FAIL;
 
   nsRefPtr<nsDocAccessible> doc(do_QueryObject(this));
   if (doc) {
     // Return window system accessible object for root document and tab document
     // accessibles.
     if (!doc->ParentDocument() ||
         nsWinUtils::IsWindowEmulationStarted() &&
-        nsWinUtils::IsTabDocument(doc->GetDocumentNode())) {
+        nsCoreUtils::IsTabDocument(doc->GetDocumentNode())) {
       HWND hwnd = static_cast<HWND>(doc->GetNativeWindow());
       if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW,
                                                        IID_IAccessible,
                                                        (void**)ppdispParent))) {
         return S_OK;
       }
     }
   }
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -31,16 +31,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/dom/TabChild.h"
+
 #include "nsDocAccessibleWrap.h"
 #include "ISimpleDOMDocument_i.c"
 #include "nsIAccessibilityService.h"
 #include "nsRootAccessible.h"
 #include "nsWinUtils.h"
 
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeNode.h"
@@ -237,17 +239,17 @@ STDMETHODIMP nsDocAccessibleWrap::get_ac
 // nsAccessNode
 
 void
 nsDocAccessibleWrap::Shutdown()
 {
   // Do window emulation specific shutdown if emulation was started.
   if (nsWinUtils::IsWindowEmulationStarted()) {
     // Destroy window created for root document.
-    if (nsWinUtils::IsTabDocument(mDocument)) {
+    if (nsCoreUtils::IsTabDocument(mDocument)) {
       sHWNDCache.Remove(mHWND);
       ::DestroyWindow(static_cast<HWND>(mHWND));
     }
 
     mHWND = nsnull;
   }
 
   nsDocAccessible::Shutdown();
@@ -267,34 +269,44 @@ nsDocAccessibleWrap::GetNativeWindow() c
 
 void
 nsDocAccessibleWrap::NotifyOfInitialUpdate()
 {
   nsDocAccessible::NotifyOfInitialUpdate();
 
   if (nsWinUtils::IsWindowEmulationStarted()) {
     // Create window for tab document.
-    if (nsWinUtils::IsTabDocument(mDocument)) {
+    if (nsCoreUtils::IsTabDocument(mDocument)) {
+      mozilla::dom::TabChild* tabChild =
+        mozilla::dom::GetTabChildFrom(mDocument->GetShell());
+
       nsRootAccessible* rootDocument = RootAccessible();
 
+      mozilla::WindowsHandle nativeData = nsnull;
+      if (tabChild)
+        tabChild->SendGetWidgetNativeData(&nativeData);
+      else
+        nativeData = reinterpret_cast<mozilla::WindowsHandle>(
+          rootDocument->GetNativeWindow());
+
       PRBool isActive = PR_TRUE;
       PRInt32 x = CW_USEDEFAULT, y = CW_USEDEFAULT, width = 0, height = 0;
       if (nsWinUtils::IsWindowEmulationFor(kDolphinModuleHandle)) {
         GetBounds(&x, &y, &width, &height);
         PRInt32 rootX = 0, rootY = 0, rootWidth = 0, rootHeight = 0;
         rootDocument->GetBounds(&rootX, &rootY, &rootWidth, &rootHeight);
         x = rootX - x;
         y -= rootY;
 
         nsCOMPtr<nsISupports> container = mDocument->GetContainer();
         nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
         docShell->GetIsActive(&isActive);
       }
 
-      HWND parentWnd = static_cast<HWND>(rootDocument->GetNativeWindow());
+      HWND parentWnd = reinterpret_cast<HWND>(nativeData);
       mHWND = nsWinUtils::CreateNativeWindow(kClassNameTabContent, parentWnd,
                                              x, y, width, height, isActive);
 
       sHWNDCache.Put(mHWND, this);
 
     } else {
       nsDocAccessible* parentDocument = ParentDocument();
       if (parentDocument)
--- a/accessible/src/msaa/nsRootAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsRootAccessibleWrap.cpp
@@ -59,17 +59,17 @@ nsRootAccessibleWrap::~nsRootAccessibleW
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsRootAccessible
 
 void
 nsRootAccessibleWrap::DocumentActivated(nsDocAccessible* aDocument)
 {
   if (nsWinUtils::IsWindowEmulationFor(kDolphinModuleHandle) &&
-      nsWinUtils::IsTabDocument(aDocument->GetDocumentNode())) {
+      nsCoreUtils::IsTabDocument(aDocument->GetDocumentNode())) {
     PRUint32 count = mChildDocuments.Length();
     for (PRUint32 idx = 0; idx < count; idx++) {
       nsDocAccessible* childDoc = mChildDocuments[idx];
       HWND childDocHWND = static_cast<HWND>(childDoc->GetNativeWindow());
       if (childDoc != aDocument)
         nsWinUtils::HideNativeWindow(childDocHWND);
       else
         nsWinUtils::ShowNativeWindow(childDocHWND);
--- a/accessible/src/msaa/nsWinUtils.cpp
+++ b/accessible/src/msaa/nsWinUtils.cpp
@@ -176,23 +176,8 @@ nsWinUtils::HideNativeWindow(HWND aWnd)
 bool
 nsWinUtils::IsWindowEmulationFor(LPCWSTR kModuleHandle)
 {
   return kModuleHandle ? ::GetModuleHandleW(kModuleHandle) :
     ::GetModuleHandleW(kJAWSModuleHandle) ||
     ::GetModuleHandleW(kWEModuleHandle)  ||
     ::GetModuleHandleW(kDolphinModuleHandle);
 }
-
-bool
-nsWinUtils::IsTabDocument(nsIDocument* aDocumentNode)
-{
-  nsCOMPtr<nsISupports> container = aDocumentNode->GetContainer();
-  nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
-
-  nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
-  treeItem->GetParent(getter_AddRefs(parentTreeItem));
-
-  nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
-  treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
-
-  return parentTreeItem == rootTreeItem;
-}
--- a/accessible/src/msaa/nsWinUtils.h
+++ b/accessible/src/msaa/nsWinUtils.h
@@ -99,17 +99,12 @@ public:
    * Helper to hide window.
    */
   static void HideNativeWindow(HWND aWnd);
 
   /**
    * Return true if window emulation is enabled.
    */
   static bool IsWindowEmulationFor(LPCWSTR kModuleHandle);
-
-  /**
-   * Return true if the given document node is for tab document accessible.
-   */
-  static bool IsTabDocument(nsIDocument* aDocumentNode);
 };
 
 #endif
 
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -57,16 +57,17 @@ using nsIntSize;
 using nsQueryContentEvent;
 using nsRect;
 using nsSelectionEvent;
 using nsTextEvent;
 using nsMouseEvent;
 using nsMouseScrollEvent;
 using nsKeyEvent;
 using RemoteDOMEvent;
+using mozilla::WindowsHandle;
 
 namespace mozilla {
 namespace dom {
 
 rpc protocol PBrowser
 {
     manager PContent;
 
@@ -178,16 +179,21 @@ parent:
 
     SetIMEOpenState(PRBool value);
 
     /**
      * Gets the DPI of the screen corresponding to this browser.
      */
     sync GetDPI() returns (float value);
 
+    /**
+     * Return native data of root widget
+     */
+    sync GetWidgetNativeData() returns (WindowsHandle value);
+
     SetCursor(PRUint32 value);
 
     PContentPermissionRequest(nsCString aType, URI uri);
 
     PContentDialog(PRUint32 aType, nsCString aName, nsCString aFeatures,
                    PRInt32[] aIntParams, nsString[] aStringParams);
 
     /**
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -63,16 +63,17 @@
 #include "nsContentPermissionHelper.h"
 #include "nsIDOMNSHTMLFrameElement.h"
 #include "nsIDialogCreator.h"
 #include "nsThreadUtils.h"
 #include "nsSerializationHelper.h"
 #include "nsIPromptFactory.h"
 #include "nsIContent.h"
 #include "nsIWidget.h"
+#include "nsIViewManager.h"
 #include "mozilla/unused.h"
 #include "nsDebug.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layout;
 
 // The flags passed by the webProgress notifications are 16 bits shifted
@@ -608,16 +609,39 @@ TabParent::RecvGetDPI(float* aValue)
 {
   NS_ABORT_IF_FALSE(mDPI > 0, 
                     "Must not ask for DPI before OwnerElement is received!");
   *aValue = mDPI;
   return true;
 }
 
 bool
+TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
+{
+  nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
+  if (content) {
+    nsIDocument* document = content->GetOwnerDoc();
+    if (document) {
+      nsIPresShell* shell = document->GetShell();
+      if (shell) {
+        nsIViewManager* vm = shell->GetViewManager();
+        nsCOMPtr<nsIWidget> widget;
+        vm->GetRootWidget(getter_AddRefs(widget));
+        if (widget) {
+          *aValue = reinterpret_cast<WindowsHandle>(
+            widget->GetNativeData(NS_NATIVE_WINDOW));
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+
+bool
 TabParent::ReceiveMessage(const nsString& aMessage,
                           PRBool aSync,
                           const nsString& aJSON,
                           InfallibleTArray<nsString>* aJSONRetVal)
 {
   nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
   if (frameLoader && frameLoader->GetFrameMessageManager()) {
     nsRefPtr<nsFrameMessageManager> manager =
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -104,16 +104,17 @@ public:
     virtual bool RecvEndIMEComposition(const PRBool& aCancel,
                                        nsString* aComposition);
     virtual bool RecvGetIMEEnabled(PRUint32* aValue);
     virtual bool RecvSetInputMode(const PRUint32& aValue, const nsString& aType, const nsString& aAction, const PRUint32& aReason);
     virtual bool RecvGetIMEOpenState(PRBool* aValue);
     virtual bool RecvSetIMEOpenState(const PRBool& aValue);
     virtual bool RecvSetCursor(const PRUint32& aValue);
     virtual bool RecvGetDPI(float* aValue);
+    virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue);
     virtual PContentDialogParent* AllocPContentDialog(const PRUint32& aType,
                                                       const nsCString& aName,
                                                       const nsCString& aFeatures,
                                                       const InfallibleTArray<int>& aIntParams,
                                                       const InfallibleTArray<nsString>& aStringParams);
     virtual bool DeallocPContentDialog(PContentDialogParent* aDialog)
     {
       delete aDialog;
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -71,16 +71,20 @@ namespace base { class FileDescriptor { 
 using mozilla::layers::LayerManager;
 
 namespace mozilla {
 
 typedef gfxPattern::GraphicsFilter GraphicsFilterType;
 typedef gfxASurface::gfxSurfaceType gfxSurfaceType;
 typedef LayerManager::LayersBackend LayersBackend;
 
+// This is a cross-platform approximation to HANDLE, which we expect
+// to be typedef'd to void* or thereabouts.
+typedef uintptr_t WindowsHandle;
+
 // XXX there are out of place and might be generally useful.  Could
 // move to nscore.h or something.
 struct void_t {
   bool operator==(const void_t&) const { return true; }
 };
 struct null_t {
   bool operator==(const null_t&) const { return true; }
 };