Bug 795275 - Introduce an explicit mechanism for determining if a script is from XBL. v1 r=mrbkap a=akeybl
authorBobby Holley <bobbyholley@gmail.com>
Sat, 22 Dec 2012 15:06:35 -0800
changeset 109957 60e0608c2c2a5d67dd38b2edca46648c36cc0952
parent 109956 090ce51386d201c0282378e8a857f2087e60b579
child 109958 8c019db3aa17c3abc3011e8f4da106218c646b5d
push id81
push userdkeeler@mozilla.com
push dateSat, 22 Dec 2012 23:14:40 +0000
reviewersmrbkap, akeybl
bugs795275
milestone17.0.1esrpre
Bug 795275 - Introduce an explicit mechanism for determining if a script is from XBL. v1 r=mrbkap a=akeybl
content/events/src/nsEventListenerManager.cpp
content/xbl/src/nsXBLProtoImplMethod.cpp
content/xbl/src/nsXBLProtoImplProperty.cpp
content/xbl/src/nsXBLPrototypeHandler.cpp
dom/base/nsIScriptContext.h
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
js/src/jsdbgapi.cpp
js/src/jsdbgapi.h
js/src/jsscript.cpp
js/src/jsscript.h
js/xpconnect/wrappers/AccessCheck.cpp
js/xpconnect/wrappers/AccessCheck.h
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -759,16 +759,17 @@ nsEventListenerManager::CompileEventHand
                                      aListenerStruct->mTypeAtom,
                                      &argCount, &argNames);
 
     result = context->CompileEventHandler(aListenerStruct->mTypeAtom,
                                           argCount, argNames,
                                           *body,
                                           url.get(), lineNo,
                                           SCRIPTVERSION_DEFAULT, // for now?
+                                          /* aIsXBL = */ false,
                                           handler);
     if (result == NS_ERROR_ILLEGAL_VALUE) {
       NS_WARNING("Probably a syntax error in the event handler!");
       return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;
     }
     NS_ENSURE_SUCCESS(result, result);
   }
 
--- a/content/xbl/src/nsXBLProtoImplMethod.cpp
+++ b/content/xbl/src/nsXBLProtoImplMethod.cpp
@@ -203,17 +203,18 @@ nsXBLProtoImplMethod::CompileMember(nsIS
   nsresult rv = aContext->CompileFunction(aClassObject,
                                           cname,
                                           paramCount,
                                           const_cast<const char**>(args),
                                           body, 
                                           functionUri.get(),
                                           uncompiledMethod->mBodyText.GetLineNumber(),
                                           JSVERSION_LATEST,
-                                          true,
+                                          /* aShared = */ true,
+                                          /* aIsXBL = */ true,
                                           &methodObject);
 
   // Destroy our uncompiled method and delete our arg list.
   delete uncompiledMethod;
   delete [] args;
   if (NS_FAILED(rv)) {
     SetUncompiledMethod(nullptr);
     return rv;
--- a/content/xbl/src/nsXBLProtoImplProperty.cpp
+++ b/content/xbl/src/nsXBLProtoImplProperty.cpp
@@ -212,17 +212,18 @@ nsXBLProtoImplProperty::CompileMember(ns
                                      NS_LITERAL_CSTRING("get_") +
                                      NS_ConvertUTF16toUTF8(mName),
                                      0,
                                      nullptr,
                                      getter, 
                                      functionUri.get(),
                                      mGetterText->GetLineNumber(),
                                      JSVERSION_LATEST,
-                                     true,
+                                     /* aShared = */ true,
+                                     /* aIsXBL = */ true,
                                      &getterObject);
 
       // Make sure we free mGetterText here before setting mJSGetterObject, since
       // that'll overwrite mGetterText
       delete mGetterText;
       deletedGetter = true;
       mJSGetterObject = getterObject;
     
@@ -262,17 +263,18 @@ nsXBLProtoImplProperty::CompileMember(ns
                                      NS_LITERAL_CSTRING("set_") +
                                      NS_ConvertUTF16toUTF8(mName),
                                      1,
                                      gPropertyArgs,
                                      setter, 
                                      functionUri.get(),
                                      mSetterText->GetLineNumber(),
                                      JSVERSION_LATEST,
-                                     true,
+                                     /* aShared = */ true,
+                                     /* aIsXBL = */ true,
                                      &setterObject);
 
       // Make sure we free mSetterText here before setting mJSGetterObject, since
       // that'll overwrite mSetterText
       delete mSetterText;
       deletedSetter = true;
       mJSSetterObject = setterObject;
 
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -335,17 +335,19 @@ nsXBLPrototypeHandler::EnsureEventHandle
   uint32_t argCount;
   const char **argNames;
   nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, &argCount,
                                    &argNames);
   nsresult rv = aBoundContext->CompileEventHandler(aName, argCount, argNames,
                                                    handlerText,
                                                    bindingURI.get(), 
                                                    mLineNumber,
-                                                   JSVERSION_LATEST, aHandler);
+                                                   JSVERSION_LATEST,
+                                                   /* aIsXBL = */ true,
+                                                   aHandler);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (pWindow) {
     pWindow->CacheXBLPrototypeHandler(this, aHandler);
   }
 
   return NS_OK;
 }
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -176,16 +176,17 @@ public:
    */
   virtual nsresult CompileEventHandler(nsIAtom* aName,
                                        uint32_t aArgCount,
                                        const char** aArgNames,
                                        const nsAString& aBody,
                                        const char* aURL,
                                        uint32_t aLineNo,
                                        uint32_t aVersion,
+                                       bool aIsXBL,
                                        nsScriptObjectHolder<JSObject>& aHandler) = 0;
 
   /**
    * Call the function object with given args and return its boolean result,
    * or true if the result isn't boolean.
    *
    * @param aTarget the event target
    * @param aScript an object telling the scope in which to call the compiled
@@ -236,16 +237,17 @@ public:
                                    const nsACString& aName,
                                    uint32_t aArgCount,
                                    const char** aArgArray,
                                    const nsAString& aBody,
                                    const char* aURL,
                                    uint32_t aLineNo,
                                    uint32_t aVersion,
                                    bool aShared,
+                                   bool aIsXBL,
                                    JSObject** aFunctionObject) = 0;
 
   /**
    * Return the global object.
    *
    **/
   virtual nsIScriptGlobalObject *GetGlobalObject() = 0;
 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -53,16 +53,17 @@
 #include "prmem.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "nsScriptNameSpaceManager.h"
 #include "StructuredCloneTags.h"
 #include "mozilla/dom/ImageData.h"
 
 #include "nsJSPrincipals.h"
+#include "jsdbgapi.h"
 
 #ifdef XP_MACOSX
 // AssertMacros.h defines 'check' and conflicts with AccessCheck.h
 #undef check
 #endif
 #include "AccessCheck.h"
 
 #ifdef MOZ_JSDEBUGGER
@@ -1718,16 +1719,17 @@ nsJSContext::JSObjectFromInterface(nsISu
 
 nsresult
 nsJSContext::CompileEventHandler(nsIAtom *aName,
                                  uint32_t aArgCount,
                                  const char** aArgNames,
                                  const nsAString& aBody,
                                  const char *aURL, uint32_t aLineNo,
                                  uint32_t aVersion,
+                                 bool aIsXBL,
                                  nsScriptObjectHolder<JSObject>& aHandler)
 {
   NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (url: %s, line: %d)", MOZ_FUNCTION_NAME,
                            __LINE__, aURL, aLineNo);
 
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name");
@@ -1764,32 +1766,38 @@ nsJSContext::CompileEventHandler(nsIAtom
                                         aArgCount, aArgNames,
                                         PromiseFlatString(aBody).get(), aBody.Length());
 
   if (!fun) {
     ReportPendingException();
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
+  // If this is an XBL function, make a note to that effect on its script.
+  if (aIsXBL) {
+    JS_SetScriptUserBit(JS_GetFunctionScript(mContext, fun), true);
+  }
+
   JSObject *handler = ::JS_GetFunctionObject(fun);
   return aHandler.set(handler);
 }
 
 // XXX - note that CompileFunction doesn't yet play the nsScriptObjectHolder
 // game - caller must still ensure JS GC root.
 nsresult
 nsJSContext::CompileFunction(JSObject* aTarget,
                              const nsACString& aName,
                              uint32_t aArgCount,
                              const char** aArgArray,
                              const nsAString& aBody,
                              const char* aURL,
                              uint32_t aLineNo,
                              uint32_t aVersion,
                              bool aShared,
+                             bool aIsXBL,
                              JSObject** aFunctionObject)
 {
   NS_TIME_FUNCTION_FMT(1.0, "%s (line %d) (function: %s, url: %s, line: %d)", MOZ_FUNCTION_NAME,
                        __LINE__, aName.BeginReading(), aURL, aLineNo);
 
   NS_ABORT_IF_FALSE(aFunctionObject,
     "Shouldn't call CompileFunction with null return value.");
 
@@ -1826,16 +1834,21 @@ nsJSContext::CompileFunction(JSObject* a
   JSFunction* fun = JS::CompileFunction(mContext, target,
                                         options, PromiseFlatCString(aName).get(),
                                         aArgCount, aArgArray,
                                         PromiseFlatString(aBody).get(), aBody.Length());
 
   if (!fun)
     return NS_ERROR_FAILURE;
 
+  // If this is an XBL function, make a note to that effect on its script.
+  if (aIsXBL) {
+    JS_SetScriptUserBit(JS_GetFunctionScript(mContext, fun), true);
+  }
+
   *aFunctionObject = JS_GetFunctionObject(fun);
   return NS_OK;
 }
 
 nsresult
 nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
                               JSObject* aHandler, nsIArray* aargv,
                               nsIVariant** arv)
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -80,16 +80,17 @@ public:
                                  bool* aIsUndefined);
 
   virtual nsresult CompileEventHandler(nsIAtom *aName,
                                        uint32_t aArgCount,
                                        const char** aArgNames,
                                        const nsAString& aBody,
                                        const char *aURL, uint32_t aLineNo,
                                        uint32_t aVersion,
+                                       bool aIsXBL,
                                        nsScriptObjectHolder<JSObject>& aHandler);
   virtual nsresult CallEventHandler(nsISupports* aTarget, JSObject* aScope,
                                     JSObject* aHandler,
                                     nsIArray *argv, nsIVariant **rv);
   virtual nsresult BindCompiledEventHandler(nsISupports *aTarget,
                                             JSObject *aScope,
                                             JSObject* aHandler,
                                             nsScriptObjectHolder<JSObject>& aBoundHandler);
@@ -97,16 +98,17 @@ public:
                                    const nsACString& aName,
                                    uint32_t aArgCount,
                                    const char** aArgArray,
                                    const nsAString& aBody,
                                    const char* aURL,
                                    uint32_t aLineNo,
                                    uint32_t aVersion,
                                    bool aShared,
+                                   bool aIsXBL,
                                    JSObject** aFunctionObject);
 
   virtual nsIScriptGlobalObject *GetGlobalObject();
   inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; };
 
   virtual JSContext* GetNativeContext();
   virtual JSObject* GetNativeGlobal();
   virtual nsresult InitContext();
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -687,16 +687,28 @@ JS_GetScriptLineExtent(JSContext *cx, JS
 }
 
 JS_PUBLIC_API(JSVersion)
 JS_GetScriptVersion(JSContext *cx, JSScript *script)
 {
     return VersionNumber(script->getVersion());
 }
 
+JS_PUBLIC_API(JSBool)
+JS_GetScriptUserBit(JSScript *script)
+{
+    return script->userBit;
+}
+
+JS_PUBLIC_API(void)
+JS_SetScriptUserBit(JSScript *script, JSBool b)
+{
+    script->userBit = b;
+}
+
 /***************************************************************************/
 
 JS_PUBLIC_API(void)
 JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata)
 {
     rt->debugHooks.newScriptHook = hook;
     rt->debugHooks.newScriptHookData = callerdata;
 }
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -290,16 +290,22 @@ extern JS_PUBLIC_API(unsigned)
 JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(unsigned)
 JS_GetScriptLineExtent(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(JSVersion)
 JS_GetScriptVersion(JSContext *cx, JSScript *script);
 
+extern JS_PUBLIC_API(JSBool)
+JS_GetScriptUserBit(JSScript *script);
+
+extern JS_PUBLIC_API(void)
+JS_SetScriptUserBit(JSScript *script, JSBool b);
+
 /************************************************************************/
 
 /*
  * Hook setters for script creation and destruction, see jsprvtd.h for the
  * typedefs.  These macros provide binary compatibility and newer, shorter
  * synonyms.
  */
 #define JS_SetNewScriptHook     JS_SetNewScriptHookProc
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -2162,16 +2162,17 @@ js::CloneScript(JSContext *cx, HandleObj
     dst->strictModeCode = src->strictModeCode;
     dst->explicitUseStrict = src->explicitUseStrict;
     dst->bindingsAccessedDynamically = src->bindingsAccessedDynamically;
     dst->funHasExtensibleScope = src->funHasExtensibleScope;
     dst->funHasAnyAliasedFormal = src->funHasAnyAliasedFormal;
     dst->hasSingletons = src->hasSingletons;
     dst->isGenerator = src->isGenerator;
     dst->isGeneratorExp = src->isGeneratorExp;
+    dst->userBit = src->userBit;
 
     /*
      * initScriptCounts updates scriptCountsMap if necessary. The other script
      * maps in JSCompartment are populated lazily.
      */
     if (cx->hasRunOption(JSOPTION_PCCOUNT))
         (void) dst->initScriptCounts(cx);
 
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -470,16 +470,17 @@ struct JSScript : public js::gc::Cell
     bool            isGenerator:1;    /* is a generator */
     bool            isGeneratorExp:1; /* is a generator expression */
     bool            hasScriptCounts:1;/* script has an entry in
                                          JSCompartment::scriptCountsMap */
     bool            hasDebugScript:1; /* script has an entry in
                                          JSCompartment::debugScriptMap */
     bool            hasFreezeConstraints:1; /* freeze constraints for stack
                                              * type sets have been generated */
+    bool            userBit:1; /* Opaque, used by the embedding. */
 
   private:
     /* See comments below. */
     bool            argsHasVarBinding_:1;
     bool            needsArgsAnalysis_:1;
     bool            needsArgsObj_:1;
 
     //
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -248,16 +248,25 @@ AccessCheck::isCrossOriginAccessPermitte
         return true;
 
     return (act == Wrapper::SET)
            ? nsContentUtils::IsCallerTrustedForWrite()
            : nsContentUtils::IsCallerTrustedForRead();
 }
 
 bool
+AccessCheck::callerIsXBL(JSContext *cx)
+{
+    JSScript *script;
+    if (!JS_DescribeScriptedCaller(cx, &script, nullptr) || !script)
+        return false;
+    return JS_GetScriptUserBit(script);
+}
+
+bool
 AccessCheck::isSystemOnlyAccessPermitted(JSContext *cx)
 {
     nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
     if (!ssm) {
         return true;
     }
 
     JSStackFrame *fp;
--- a/js/xpconnect/wrappers/AccessCheck.h
+++ b/js/xpconnect/wrappers/AccessCheck.h
@@ -21,16 +21,17 @@ class AccessCheck {
     static bool subsumes(JSCompartment *a, JSCompartment *b);
     static bool subsumes(JSObject *a, JSObject *b);
     static bool subsumesIgnoringDomain(JSCompartment *a, JSCompartment *b);
     static bool isChrome(JSCompartment *compartment);
     static bool callerIsChrome();
     static nsIPrincipal *getPrincipal(JSCompartment *compartment);
     static bool isCrossOriginAccessPermitted(JSContext *cx, JSObject *obj, jsid id,
                                              js::Wrapper::Action act);
+    static bool callerIsXBL(JSContext *cx);
     static bool isSystemOnlyAccessPermitted(JSContext *cx);
     static bool isLocationObjectSameOrigin(JSContext *cx, JSObject *wrapper);
 
     static bool needsSystemOnlyWrapper(JSObject *obj);
 
     static bool isScriptAccessOnly(JSContext *cx, JSObject *wrapper);
 
     static void deny(JSContext *cx, jsid id);