Bug 758563 - Warn when __exposedProps__ is missing. r=bz
authorBobby Holley <bobbyholley@gmail.com>
Fri, 25 May 2012 18:42:40 +0200
changeset 97237 6c7d23818d34097afe6999d8cd7d31c298a3d035
parent 97236 49859cdadbc44eb99f292c375a5220e5f78ec6ed
child 97238 53aaa1c7823ab006649777d1f6c214aaa4485202
push id1439
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 20:19:22 +0000
treeherdermozilla-aurora@ea74834dccd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs758563
milestone15.0a1
Bug 758563 - Warn when __exposedProps__ is missing. r=bz
content/base/public/nsDeprecatedOperationList.h
dom/locales/en-US/chrome/dom/dom.properties
js/xpconnect/tests/chrome/Makefile.in
js/xpconnect/tests/chrome/test_bug758563.xul
js/xpconnect/tests/mochitest/Makefile.in
js/xpconnect/tests/mochitest/file_bug758563.html
js/xpconnect/wrappers/AccessCheck.cpp
--- a/content/base/public/nsDeprecatedOperationList.h
+++ b/content/base/public/nsDeprecatedOperationList.h
@@ -40,9 +40,10 @@ DEPRECATED_OPERATION(IsEqualNode)
 DEPRECATED_OPERATION(TextContent)
 DEPRECATED_OPERATION(EnablePrivilege)
 DEPRECATED_OPERATION(Position)
 DEPRECATED_OPERATION(TotalSize)
 DEPRECATED_OPERATION(InputEncoding)
 DEPRECATED_OPERATION(MozBeforePaint)
 DEPRECATED_OPERATION(MozBlobBuilder)
 DEPRECATED_OPERATION(DOMExceptionCode)
+DEPRECATED_OPERATION(NoExposedProps)
 DEPRECATED_OPERATION(MutationEvent)
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -115,10 +115,12 @@ MediaLoadSourceMediaNotMatched=Specified
 # LOCALIZATION NOTE: %1$S is the MIME type HTTP header being sent by the web server, %2$S is the URL of the media resource which failed to load.
 MediaLoadUnsupportedMimeType=HTTP "Content-Type" of "%1$S" is not supported. Load of media resource %2$S failed.
 # LOCALIZATION NOTE: %S is the URL of the media resource which failed to load because of error in decoding.
 MediaLoadDecodeError=Media resource %S could not be decoded.
 # LOCALIZATION NOTE: Do not translate "MozBlobBuilder" and "Blob"
 MozBlobBuilderWarning=Use of MozBlobBuilder is deprecated. Use Blob constructor instead.
 # LOCALIZATION NOTE: Do not translate "DOMException", "code" and "name"
 DOMExceptionCodeWarning=Use of DOMException's code attribute is deprecated. Use name instead.
+# LOCALIZATION NOTE: Do not translate "__exposedProps__"
+NoExposedPropsWarning=Exposing chrome JS objects to content without __exposedProps__ is insecure and deprecated. See https://developer.mozilla.org/en/XPConnect_wrappers for more information.
 # LOCALIZATION NOTE: Do not translate "Mutation Event" and "MutationObserver"
 MutationEventWarning=Use of Mutation Events is deprecated. Use MutationObserver instead.
--- a/js/xpconnect/tests/chrome/Makefile.in
+++ b/js/xpconnect/tests/chrome/Makefile.in
@@ -42,16 +42,17 @@ include $(topsrcdir)/config/rules.mk
 		test_APIExposer.xul \
 		test_precisegc.xul \
 		test_nodelists.xul \
 		test_getweakmapkeys.xul \
 		test_weakmaps.xul \
 		test_exnstack.xul \
 		test_weakref.xul \
 		test_bug726949.xul \
+		test_bug758563.xul \
 		$(NULL)
 
 # Disabled until this test gets updated to test the new proxy based
 # wrappers.
 #		test_wrappers-2.xul \
 
 # Disabled due to apparent conservative stack scanner false positives on Linux64 debug.
 #		test_watchpoints.xul \
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_bug758563.xul
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=758563
+-->
+<window title="Mozilla Bug 758563"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=758563"
+     target="_blank">Mozilla Bug 758563</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+
+  /** Test for deprecation warnings for non-__exposedProps__ COWs. **/
+
+  SimpleTest.waitForExplicitFinish();
+
+  // Set up our console listener.
+  var gWarnings = 0;
+  function onWarning(consoleMessage) {
+    if (/__exposedProps__/.test(consoleMessage.message))
+      gWarnings++;
+  }
+  var gListener = {
+    observe: onWarning,
+    QueryInterface: function (iid) {
+      if (!iid.equals(Components.interfaces.nsIConsoleListener) &&
+          !iid.equals(Components.interfaces.nsISupports)) {
+        throw Components.results.NS_ERROR_NO_INTERFACE;
+      }
+      return this;
+    }
+  };
+  var gConsoleService = Components.classes["@mozilla.org/consoleservice;1"]
+                                  .getService(Components.interfaces.nsIConsoleService);
+  gConsoleService.registerListener(gListener);
+
+  // Wait for both child frame to load.
+  var gLoadCount = 0;
+  function frameLoaded() {
+    if (++gLoadCount == 2)
+      go();
+  }
+
+  function go() {
+    testFor('frame1');
+    testFor('frame2');
+
+    // Warnings are dispatched async, so stick ourselves at the end of the event
+    // queue.
+    setTimeout(done, 0);
+  }
+
+  function testFor(id) {
+    var win = document.getElementById(id).contentWindow.wrappedJSObject;
+    win.chromeObj = {a: 42};
+    win.ok = ok;
+    win.is = is;
+    win.doAccess();
+  }
+
+  function done() {
+    gConsoleService.unregisterListener(gListener);
+    is(gWarnings, 2, "Got the right number of warnings");
+    SimpleTest.finish();
+  }
+
+  ]]>
+
+  </script>
+  <iframe id="frame1" onload="frameLoaded();" type="content" src="http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_bug758563.html" />
+  <iframe id="frame2" onload="frameLoaded();" type="content" src="http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_bug758563.html" />
+</window>
--- a/js/xpconnect/tests/mochitest/Makefile.in
+++ b/js/xpconnect/tests/mochitest/Makefile.in
@@ -58,16 +58,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug636097.html \
 		test_bug661980.html \
 		test_bug650273.html \
 		file_bug650273.html \
 		file_bug658560.html \
 		test_bug655297.html \
 		test_bug691059.html \
 		test_bug745483.html \
+		file_bug758563.html \
 		file_nodelists.html \
 		file_bug706301.html \
 		file_exnstack.html \
 		$(NULL)
 
 _CHROME_FILES	= \
 		test_bug361111.xul \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/mochitest/file_bug758563.html
@@ -0,0 +1,19 @@
+<html>
+<head>
+<script type="application/javascript">
+  function doAccess() {
+    // Access the variable twice.
+    oneAccess();
+    oneAccess();
+  }
+
+  function oneAccess() {
+    try {
+      is(window.chromeObj.a, 42, "Successfully read chrome property");
+    } catch (e) { ok(false, "Threw while trying to access chrome property"); };
+  }
+</script>
+</head>
+<body>
+</body>
+</html>
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/Util.h"
 
 #include "AccessCheck.h"
 
 #include "nsJSPrincipals.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMWindowCollection.h"
 #include "nsContentUtils.h"
+#include "nsJSUtils.h"
 
 #include "XPCWrapper.h"
 #include "XrayWrapper.h"
 #include "FilteringWrapper.h"
 
 #include "jsfriendapi.h"
 
 using namespace mozilla;
@@ -484,16 +485,31 @@ ExposedPropertiesOnly::check(JSContext *
         perm = PermitPropertyAccess;
         return true; // Allow
     }
 
     // If no __exposedProps__ existed, deny access.
     if (!found) {
         // For now, only do this on functions.
         if (!JS_ObjectIsFunction(cx, wrappedObject)) {
+
+            // This little loop hole will go away soon! See bug 553102.
+            JSAutoEnterCompartment innerAc;
+            if (!innerAc.enter(cx, wrapper))
+                return false;
+            nsCOMPtr<nsPIDOMWindow> win =
+                do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, wrapper));
+            if (win) {
+                nsCOMPtr<nsIDocument> doc =
+                    do_QueryInterface(win->GetExtantDocument());
+                if (doc) {
+                    doc->WarnOnceAbout(nsIDocument::eNoExposedProps);
+                }
+            }
+
             perm = PermitPropertyAccess;
             return true;
         }
         return PermitIfUniversalXPConnect(cx, id, act, perm); // Deny
     }
 
     if (id == JSID_VOID) {
         // This will force the caller to call us back for individual property accesses.