Bug 760802 - Add JS nativeHandler attribute for nsIBaseWindow. r=roc
authorfoudfou <foudil.newbie+bugzilla.mozilla.org@gmail.com>
Tue, 24 Jul 2012 21:35:32 -0400
changeset 100359 9dcd7470dc0b8c887abc202c73ff5df98f0f7423
parent 100358 063027b49a09e61b069cf313d2ed497056f3e15d
child 100360 1c521e0a117e76b9e2f8983931e5f3f3965ecaec
push id23175
push useremorley@mozilla.com
push dateWed, 25 Jul 2012 15:03:49 +0000
treeherdermozilla-central@75d16b99e8ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs760802
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 760802 - Add JS nativeHandler attribute for nsIBaseWindow. r=roc
docshell/base/nsDocShell.cpp
embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
embedding/browser/webBrowser/nsWebBrowser.cpp
widget/nsIBaseWindow.idl
widget/tests/Makefile.in
widget/tests/test_bug760802.html
xpfe/appshell/src/nsChromeTreeOwner.cpp
xpfe/appshell/src/nsContentTreeOwner.cpp
xpfe/appshell/src/nsXULWindow.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -4897,16 +4897,23 @@ nsDocShell::GetParentNativeWindow(native
 
 NS_IMETHODIMP
 nsDocShell::SetParentNativeWindow(nativeWindow parentNativeWindow)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+nsDocShell::GetNativeHandle(nsAString& aNativeHandle)
+{
+    // the nativeHandle should be accessed from nsIXULWindow
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 nsDocShell::GetVisibility(bool * aVisibility)
 {
     NS_ENSURE_ARG_POINTER(aVisibility);
 
     *aVisibility = false;
 
     if (!mContentViewer)
         return NS_OK;
--- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
@@ -579,16 +579,23 @@ nsDocShellTreeOwner::GetParentNativeWind
 
 NS_IMETHODIMP
 nsDocShellTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow)
 {
   return NS_ERROR_NULL_POINTER;
 }
 
 NS_IMETHODIMP
+nsDocShellTreeOwner::GetNativeHandle(nsAString& aNativeHandle)
+{
+  // the nativeHandle should be accessed from nsIXULWindow
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 nsDocShellTreeOwner::GetVisibility(bool* aVisibility)
 {
   nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
   if (ownerWin)
   {
     return ownerWin->GetVisibility(aVisibility);
   }
   return NS_ERROR_NULL_POINTER;
--- a/embedding/browser/webBrowser/nsWebBrowser.cpp
+++ b/embedding/browser/webBrowser/nsWebBrowser.cpp
@@ -1373,16 +1373,22 @@ NS_IMETHODIMP nsWebBrowser::SetParentNat
 {
    NS_ENSURE_STATE(!mDocShell);
 
    mParentNativeWindow = aParentNativeWindow;
 
    return NS_OK;
 }
 
+NS_IMETHODIMP nsWebBrowser::GetNativeHandle(nsAString& aNativeHandle)
+{
+   // the nativeHandle should be accessed from nsIXULWindow
+   return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 NS_IMETHODIMP nsWebBrowser::GetVisibility(bool* visibility)
 {
    NS_ENSURE_ARG_POINTER(visibility);
 
    if(!mDocShell)
       *visibility = mInitInfo->visible;
    else
       NS_ENSURE_SUCCESS(mDocShellAsWin->GetVisibility(visibility), NS_ERROR_FAILURE);
--- a/widget/nsIBaseWindow.idl
+++ b/widget/nsIBaseWindow.idl
@@ -148,16 +148,27 @@ interface nsIBaseWindow : nsISupports
 	implementations.
 
 	On controls that don't support setting nativeWindow parents, setting this
 	will return a NS_ERROR_NOT_IMPLEMENTED error.
 	*/
 	attribute nativeWindow parentNativeWindow;
 
 	/*
+	This is the handle (HWND, GdkWindow*, ...) to the native window of the
+	control, exposed as a DOMString.
+
+	@return DOMString in hex format with "0x" prepended, or empty string if
+	mainWidget undefined
+
+	@throws NS_ERROR_NOT_IMPLEMENTED for non-XULWindows
+	*/
+	readonly attribute DOMString nativeHandle;
+
+	/*
 	Attribute controls the visibility of the object behind this interface.
 	Setting this attribute to false will hide the control.  Setting it to 
 	true will show it.
 	*/
 	attribute boolean visibility;
 
     /*
     a disabled window should accept no user interaction; it's a dead window,
--- a/widget/tests/Makefile.in
+++ b/widget/tests/Makefile.in
@@ -25,16 +25,19 @@ endif
 # Test disabled because it requires the internal API.  Re-enabling this test is
 # bug 652123.
 #CPP_UNIT_TESTS += TestChromeMargin.cpp  \
 #                 $(NULL)
 endif
 
 CPP_UNIT_TESTS += TestAppShellSteadyState.cpp
 
+MOCHITEST_FILES =	test_bug760802.html \
+		$(NULL)
+
 MOCHITEST_CHROME_FILES =	test_bug343416.xul \
 		test_bug429954.xul \
 		window_bug429954.xul \
 		test_bug444800.xul \
 		test_bug462106.xul \
 		test_bug478536.xul \
 		window_bug478536.xul \
 		test_bug517396.xul \
@@ -87,21 +90,21 @@ MOCHITEST_CHROME_FILES  += taskbar_previ
 		taskbar_progress.xul \
 		test_chrome_context_menus_win.xul \
 		test_plugin_input_event.html \
 		chrome_context_menus_win.xul \
 		test_mouse_scroll.xul \
 		window_mouse_scroll_win.html \
 		$(NULL)
 
-MOCHITEST_FILES =	test_bug565392.html \
+MOCHITEST_FILES +=	test_bug565392.html \
 		test_picker_no_crash.html \
 		window_picker_no_crash_child.html \
 		$(NULL)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
-MOCHITEST_FILES = 	plugin_scroll_invalidation.html \
+MOCHITEST_FILES += 	plugin_scroll_invalidation.html \
 		test_plugin_scroll_invalidation.html \
 		$(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/widget/tests/test_bug760802.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=760802
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 760802</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=760802">Mozilla Bug 760802</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<iframe id="iframe_not_editable" width="300" height="150"
+        src="data:text/html,&lt;html&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;"></iframe><br/>
+<pre id="test">
+<script type="application/javascript">
+
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+function getBaseWindowInterface(win) {
+  return win.QueryInterface(Ci.nsIInterfaceRequestor)
+    .getInterface(Ci.nsIWebNavigation)
+    .QueryInterface(Ci.nsIDocShellTreeItem)
+    .treeOwner
+    .QueryInterface(Ci.nsIInterfaceRequestor)
+    .nsIBaseWindow;
+}
+
+function shouldThrow(fun) {
+  try {
+    fun.call();
+    return false;
+  } catch (e) {
+    return true;
+  }
+}
+function doesntThrow(fun) !shouldThrow(fun)
+
+
+var baseWindow = getBaseWindowInterface(window);
+var nativeHandle = baseWindow.nativeHandle;
+$("display").innerHTML = "found nativeHandle for this window: "+nativeHandle;
+
+var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
+var win = wm.getMostRecentWindow("navigator:browser");
+var docShell = win.gBrowser.docShell;
+
+ok(
+  shouldThrow(function(){docShell.getInterface(Ci.nsIBaseWindow).nativeHandle;}),
+  "nativeHandle should not be implemented for nsDocShell"
+);
+
+ok(typeof(nativeHandle) === "string", "nativeHandle should be a string");
+ok(nativeHandle.match(/^0x[0-9a-f]+$/), "nativeHandle should have a memory address format");
+
+var iWin = window.document.getElementById("iframe_not_editable").contentWindow;
+is(getBaseWindowInterface(iWin).nativeHandle, nativeHandle,
+              "the nativeHandle of an iframe should be its parent's nativeHandle");
+
+var dialog = window.openDialog("data:text/plain,this is an active window.", "_blank",
+                               "chrome,dialog=yes,width=100,height=100");
+
+isnot(getBaseWindowInterface(dialog).nativeHandle, "",
+      "the nativeHandle of a dialog should not be empty");
+
+dialog.close();
+
+todo(false, "the nativeHandle of a window without a mainWidget should be empty"); // how to build a window without a mainWidget ?
+
+</script>
+</pre>
+</body>
+</html>
--- a/xpfe/appshell/src/nsChromeTreeOwner.cpp
+++ b/xpfe/appshell/src/nsChromeTreeOwner.cpp
@@ -413,16 +413,22 @@ NS_IMETHODIMP nsChromeTreeOwner::GetPare
 }
 
 NS_IMETHODIMP nsChromeTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow)
 {
    NS_ASSERTION(false, "You can't call this");
    return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP nsChromeTreeOwner::GetNativeHandle(nsAString& aNativeHandle)
+{
+   NS_ENSURE_STATE(mXULWindow);
+   return mXULWindow->GetNativeHandle(aNativeHandle);
+}
+
 NS_IMETHODIMP nsChromeTreeOwner::GetVisibility(bool* aVisibility)
 {
    NS_ENSURE_STATE(mXULWindow);
    return mXULWindow->GetVisibility(aVisibility);
 }
 
 NS_IMETHODIMP nsChromeTreeOwner::SetVisibility(bool aVisibility)
 {
--- a/xpfe/appshell/src/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/src/nsContentTreeOwner.cpp
@@ -630,16 +630,22 @@ NS_IMETHODIMP nsContentTreeOwner::GetPar
 }
 
 NS_IMETHODIMP nsContentTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow)
 {
    NS_ASSERTION(false, "You can't call this");
    return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP nsContentTreeOwner::GetNativeHandle(nsAString& aNativeHandle)
+{
+   NS_ENSURE_STATE(mXULWindow);
+   return mXULWindow->GetNativeHandle(aNativeHandle);
+}
+
 NS_IMETHODIMP nsContentTreeOwner::GetVisibility(bool* aVisibility)
 {
    NS_ENSURE_STATE(mXULWindow);
    return mXULWindow->GetVisibility(aVisibility);
 }
 
 NS_IMETHODIMP nsContentTreeOwner::SetVisibility(bool aVisibility)
 {
--- a/xpfe/appshell/src/nsXULWindow.cpp
+++ b/xpfe/appshell/src/nsXULWindow.cpp
@@ -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/. */
 
 // Local includes
 #include "nsXULWindow.h"
 
 // Helper classes
+#include "nsPrintfCString.h"
 #include "nsString.h"
 #include "nsWidgetsCID.h"
 #include "prprf.h"
 #include "nsCRT.h"
 #include "nsThreadUtils.h"
 #include "nsNetCID.h"
 
 //Interfaces needed to be included
@@ -733,16 +734,32 @@ NS_IMETHODIMP nsXULWindow::GetParentNati
 
 NS_IMETHODIMP nsXULWindow::SetParentNativeWindow(nativeWindow aParentNativeWindow)
 {
   //XXX First Check In
   NS_ASSERTION(false, "Not Yet Implemented");
   return NS_OK;
 }
 
+NS_IMETHODIMP nsXULWindow::GetNativeHandle(nsAString& aNativeHandle)
+{
+  nsCOMPtr<nsIWidget> mainWidget;
+  NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(mainWidget)), NS_ERROR_FAILURE);
+
+  if (mainWidget) {
+    nativeWindow nativeWindowPtr = mainWidget->GetNativeData(NS_NATIVE_WINDOW);
+    /* the nativeWindow pointer is converted to and exposed as a string. This
+       is a more reliable way not to lose information (as opposed to JS
+       |Number| for instance) */
+    aNativeHandle = NS_ConvertASCIItoUTF16(nsPrintfCString("0x%p", nativeWindowPtr));
+  }
+
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsXULWindow::GetVisibility(bool* aVisibility)
 {
   NS_ENSURE_ARG_POINTER(aVisibility);
 
   // Always claim to be visible for now. See bug
   // https://bugzilla.mozilla.org/show_bug.cgi?id=306245.
 
   *aVisibility = true;