Bug 794943 - Make window.controllers [ChromeOnly], and remove nsISecurityCheckedComponent from nsXULControllers. r=bz
authorBobby Holley <bobbyholley@gmail.com>
Thu, 16 Jan 2014 15:45:40 -0800
changeset 163892 49e949b48381f04e2fdfae1b239b2cd7b3894e46
parent 163891 56471970fe899f133f91d8ef35673a218273f96e
child 163893 8c06f2a9711508494c5842ca079cc1ae55c6e1f6
push idunknown
push userunknown
push dateunknown
reviewersbz
bugs794943
milestone29.0a1
Bug 794943 - Make window.controllers [ChromeOnly], and remove nsISecurityCheckedComponent from nsXULControllers. r=bz
content/xul/document/src/nsXULControllers.cpp
content/xul/document/src/nsXULControllers.h
dom/interfaces/base/nsIDOMWindow.idl
dom/webidl/Window.webidl
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/tests/mochitest/test_bug912322.html
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/content/xul/document/src/nsXULControllers.cpp
+++ b/content/xul/document/src/nsXULControllers.cpp
@@ -78,17 +78,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
     }
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 DOMCI_DATA(XULControllers, nsXULControllers)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULControllers)
   NS_INTERFACE_MAP_ENTRY(nsIControllers)
-  NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIControllers)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULControllers)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULControllers)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULControllers)
 
 NS_IMETHODIMP
@@ -250,58 +249,8 @@ nsXULControllers::GetControllerById(uint
 NS_IMETHODIMP
 nsXULControllers::GetControllerCount(uint32_t *_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = mControllers.Length();
   return NS_OK;
 }
 
-// nsISecurityCheckedComponent implementation
-
-static char* cloneAllAccess()
-{
-  static const char allAccess[] = "AllAccess";
-  return (char*)nsMemory::Clone(allAccess, sizeof(allAccess));
-}
-
-static char* cloneUniversalXPConnect()
-{
-  static const char universalXPConnect[] = "UniversalXPConnect";
-  return (char*)nsMemory::Clone(universalXPConnect, sizeof(universalXPConnect));
-}
-
-NS_IMETHODIMP
-nsXULControllers::CanCreateWrapper(const nsIID * iid, char **_retval)
-{
-  *_retval = cloneAllAccess();
-  return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-NS_IMETHODIMP
-nsXULControllers::CanCallMethod(const nsIID * iid, const char16_t *methodName,
-                                char **_retval)
-{
-  // OK if you're cool enough
-  *_retval = cloneUniversalXPConnect();
-  return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-NS_IMETHODIMP
-nsXULControllers::CanGetProperty(const nsIID * iid,
-                                 const char16_t *propertyName,
-                                 char **_retval)
-{
-  // OK if you're cool enough
-  *_retval = cloneUniversalXPConnect();
-  return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-
-NS_IMETHODIMP
-nsXULControllers::CanSetProperty(const nsIID * iid,
-                                 const char16_t *propertyName,
-                                 char **_retval)
-{
-  // OK if you're cool enough
-  *_retval = cloneUniversalXPConnect();
-  return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
--- a/content/xul/document/src/nsXULControllers.h
+++ b/content/xul/document/src/nsXULControllers.h
@@ -11,17 +11,16 @@
 
 #ifndef nsXULControllers_h__
 #define nsXULControllers_h__
 
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsWeakPtr.h"
 #include "nsIControllers.h"
-#include "nsISecurityCheckedComponent.h"
 #include "nsCycleCollectionParticipant.h"
 
 /* non-XPCOM class for holding controllers and their IDs */
 class nsXULControllerData
 {
 public:
                             nsXULControllerData(uint32_t inControllerID, nsIController* inController)
                             : mControllerID(inControllerID)
@@ -41,27 +40,25 @@ public:
     
     uint32_t                mControllerID;
     nsCOMPtr<nsIController> mController;
 };
 
 
 nsresult NS_NewXULControllers(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
-class nsXULControllers : public nsIControllers,
-                         public nsISecurityCheckedComponent
+class nsXULControllers : public nsIControllers
 {
 public:
     friend nsresult
     NS_NewXULControllers(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULControllers, nsIControllers)
     NS_DECL_NSICONTROLLERS
-    NS_DECL_NSISECURITYCHECKEDCOMPONENT
   
 protected:
     nsXULControllers();
     virtual ~nsXULControllers(void);
 
     void        DeleteControllers();
 
     nsTArray<nsXULControllerData*>   mControllers;
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -19,17 +19,17 @@ interface nsIVariant;
  * The nsIDOMWindow interface is the primary interface for a DOM
  * window object. It represents a single window object that may
  * contain child windows if the document in the window contains a
  * HTML frameset document or if the document contains iframe elements.
  *
  * @see <http://www.whatwg.org/html/#window>
  */
 
-[scriptable, uuid(b0ebb526-ed69-43c6-8242-b381a1fe79da)]
+[scriptable, uuid(f2d1d383-f7b5-46f8-aadf-b69a0ebfb16f)]
 interface nsIDOMWindow : nsISupports
 {
   // the current browsing context
   readonly attribute nsIDOMWindow                       window;
 
   /* [replaceable] self */
   readonly attribute nsIDOMWindow                       self;
 
@@ -371,19 +371,18 @@ interface nsIDOMWindow : nsISupports
   /* [replaceable] prompter */
   [noscript] readonly attribute nsIPrompt               prompter;
 
   readonly attribute boolean                            closed;
 
   readonly attribute nsIDOMCrypto                       crypto;
   readonly attribute nsIDOMPkcs11                       pkcs11;
 
-  // XXX Shouldn't this be in nsIDOMChromeWindow?
-  /* [replaceable] controllers */
-  readonly attribute nsIControllers                     controllers;
+  // Note: this is [ChromeOnly] scriptable via WebIDL.
+  [noscript] readonly attribute nsIControllers          controllers;
 
   readonly attribute float                              mozInnerScreenX;
   readonly attribute float                              mozInnerScreenY;
   readonly attribute float                              devicePixelRatio;
 
   /* The maximum offset that the window can be scrolled to
      (i.e., the document width/height minus the scrollport width/height) */
   readonly attribute long                               scrollMaxX;
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -255,17 +255,17 @@ partial interface Window {
   /**
    * Method for sizing this window to the content in the window.
    */
   [Throws] void             sizeToContent();
 
   readonly attribute Pkcs11?                      pkcs11;
 
   // XXX Shouldn't this be in nsIDOMChromeWindow?
-  [Replaceable, Throws] readonly attribute MozControllers controllers;
+  [ChromeOnly, Replaceable, Throws] readonly attribute MozControllers controllers;
 
   [Throws] readonly attribute float               mozInnerScreenX;
   [Throws] readonly attribute float               mozInnerScreenY;
   [Throws] readonly attribute float               devicePixelRatio;
 
   /* The maximum offset that the window can be scrolled to
      (i.e., the document width/height minus the scrollport width/height) */
   [Replaceable, Throws] readonly attribute long   scrollMaxX;
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -72,16 +72,17 @@ const char* const XPCJSRuntime::mStrings
     "Function",             // IDX_FUNCTION
     "prototype",            // IDX_PROTOTYPE
     "createInstance",       // IDX_CREATE_INSTANCE
     "item",                 // IDX_ITEM
     "__proto__",            // IDX_PROTO
     "__iterator__",         // IDX_ITERATOR
     "__exposedProps__",     // IDX_EXPOSEDPROPS
     "eval",                 // IDX_EVAL
+    "controllers",           // IDX_CONTROLLERS
 };
 
 /***************************************************************************/
 
 struct CX_AND_XPCRT_Data
 {
     JSContext* cx;
     XPCJSRuntime* rt;
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -528,16 +528,17 @@ public:
         IDX_FUNCTION                ,
         IDX_PROTOTYPE               ,
         IDX_CREATE_INSTANCE         ,
         IDX_ITEM                    ,
         IDX_PROTO                   ,
         IDX_ITERATOR                ,
         IDX_EXPOSEDPROPS            ,
         IDX_EVAL                    ,
+        IDX_CONTROLLERS             ,
         IDX_TOTAL_COUNT // just a count of the above
     };
 
     jsid GetStringID(unsigned index) const
     {
         MOZ_ASSERT(index < IDX_TOTAL_COUNT, "index out of range");
         return mStrIDs[index];
     }
--- a/js/xpconnect/tests/mochitest/test_bug912322.html
+++ b/js/xpconnect/tests/mochitest/test_bug912322.html
@@ -13,18 +13,19 @@ https://bugzilla.mozilla.org/show_bug.cg
   /** Test that XBL functions aren't exposed to the web. **/
   funs = ['getAnonymousNodes', 'getAnonymousElementByAttribute',
           'getBindingParent', 'loadBindingDocument'];
   for (var f of funs) {
     ok(!(f in document), f + " should not be available to content");
     ok(f in SpecialPowers.wrap(document), f + " should be available to chrome via Xray");
   }
 
-
-
+  // Test window.controllers.
+  ok(typeof window.controllers, 'undefined', "controllers should not be available to content");
+  ok(typeof SpecialPowers.wrap(window).controllers, 'object', "controllers should be available over Xray");
 
   </script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=912322">Mozilla Bug 912322</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -5,16 +5,17 @@
  * 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/. */
 
 #include "XrayWrapper.h"
 #include "AccessCheck.h"
 #include "WrapperFactory.h"
 
 #include "nsIContent.h"
+#include "nsIControllers.h"
 #include "nsContentUtils.h"
 
 #include "XPCWrapper.h"
 #include "xpcprivate.h"
 
 #include "jsapi.h"
 #include "jsprf.h"
 #include "nsJSUtils.h"
@@ -708,16 +709,42 @@ XPCWrappedNativeXrayTraits::resolveNativ
     // not find the property. However we want to support non shadowing dom
     // specific collection properties like window.frames, so we still have to
     // check for those.
     if (!JSID_IS_STRING(id)) {
         /* Not found */
         return resolveDOMCollectionProperty(cx, wrapper, holder, id, desc, flags);
     }
 
+
+    // The |controllers| property is accessible as a [ChromeOnly] property on
+    // Window.WebIDL, and [noscript] in XPIDL. Chrome needs to see this over
+    // Xray, so we need to special-case it until we move |Window| to WebIDL.
+    nsGlobalWindow *win = nullptr;
+    if (id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_CONTROLLERS) &&
+        AccessCheck::isChrome(wrapper) &&
+        (win = static_cast<nsGlobalWindow*>(As<nsPIDOMWindow>(wrapper))))
+    {
+        nsCOMPtr<nsIControllers> c;
+        nsresult rv = win->GetControllers(getter_AddRefs(c));
+        if (NS_SUCCEEDED(rv) && c) {
+            rv = nsXPConnect::XPConnect()->WrapNativeToJSVal(cx, CurrentGlobalOrNull(cx),
+                                                             c, nullptr, nullptr, true,
+                                                             desc.value().address());
+        }
+
+        if (NS_FAILED(rv) || !c) {
+            JS_ReportError(cx, "Failed to invoke GetControllers via Xrays");
+            return false;
+        }
+
+        desc.object().set(wrapper);
+        return true;
+    }
+
     XPCNativeInterface *iface;
     XPCNativeMember *member;
     XPCWrappedNative *wn = getWN(wrapper);
 
     if (ccx.GetWrapper() != wn || !wn->IsValid()) {
         // Something is wrong. If the wrapper is not even valid let's not risk
         // calling resolveDOMCollectionProperty.
         return true;