Bug 754771 - Add identifying information to all system compartments. r=bz
authorNils Maier <maierman@web.de>
Wed, 16 May 2012 19:42:10 +0200
changeset 99154 4e5c6770680a38818e81f054254756ae73966b13
parent 99153 f5d4d38cd4addefab58a404913385b29f0f40fe6
child 99155 aade4b52f10ee2d5ab51f4db9de474061e4fb9f7
push id173
push userlsblakk@mozilla.com
push dateFri, 24 Aug 2012 15:39:16 +0000
treeherdermozilla-release@bcc45eb1fb41 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs754771
milestone15.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 754771 - Add identifying information to all system compartments. r=bz
content/xbl/src/nsXBLDocumentInfo.cpp
content/xul/document/src/nsXULPrototypeDocument.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsIScriptContext.h
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/src/xpcpublic.h
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -39,17 +39,17 @@ static const char kXBLCachePrefix[] = "x
 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 // An XBLDocumentInfo object has a special context associated with it which we can use to pre-compile 
 // properties and methods of XBL bindings against.
 class nsXBLDocGlobalObject : public nsIScriptGlobalObject,
                              public nsIScriptObjectPrincipal
 {
 public:
-  nsXBLDocGlobalObject(nsIScriptGlobalObjectOwner *aGlobalObjectOwner);
+  nsXBLDocGlobalObject(nsXBLDocumentInfo *aGlobalObjectOwner);
 
   // nsISupports interface
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   
   // nsIScriptGlobalObject methods
   virtual nsresult EnsureScriptEnvironment();
   void ClearScriptContext()
   {
@@ -77,17 +77,17 @@ public:
 protected:
   virtual ~nsXBLDocGlobalObject();
 
   nsIScriptContext *GetScriptContext();
 
   nsCOMPtr<nsIScriptContext> mScriptContext;
   JSObject *mJSObject;
 
-  nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // weak reference
+  nsXBLDocumentInfo* mGlobalObjectOwner; // weak reference
   static JSClass gSharedGlobalClass;
 };
 
 JSBool
 nsXBLDocGlobalObject::doCheckAccess(JSContext *cx, JSObject *obj, jsid id, PRUint32 accessType)
 {
   nsIScriptSecurityManager *ssm = nsContentUtils::GetSecurityManager();
   if (!ssm) {
@@ -176,17 +176,17 @@ JSClass nsXBLDocGlobalObject::gSharedGlo
     TraceXPCGlobal
 };
 
 //----------------------------------------------------------------------
 //
 // nsXBLDocGlobalObject
 //
 
-nsXBLDocGlobalObject::nsXBLDocGlobalObject(nsIScriptGlobalObjectOwner *aGlobalObjectOwner)
+nsXBLDocGlobalObject::nsXBLDocGlobalObject(nsXBLDocumentInfo *aGlobalObjectOwner)
     : mJSObject(nsnull),
       mGlobalObjectOwner(aGlobalObjectOwner) // weak reference
 {
 }
 
 
 nsXBLDocGlobalObject::~nsXBLDocGlobalObject()
 {}
@@ -276,16 +276,21 @@ nsXBLDocGlobalObject::EnsureScriptEnviro
 
   nsIPrincipal *principal = GetPrincipal();
   JSCompartment *compartment;
 
   rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, principal, nsnull,
                               false, &mJSObject, &compartment);
   NS_ENSURE_SUCCESS(rv, NS_OK);
 
+  // Set the location information for the new global, so that tools like
+  // about:memory may use that information
+  nsIURI *ownerURI = mGlobalObjectOwner->DocumentURI();
+  xpc::SetLocationForGlobal(mJSObject, ownerURI);
+
   ::JS_SetGlobalObject(cx, mJSObject);
 
   // Add an owning reference from JS back to us. This'll be
   // released when the JSObject is finalized.
   ::JS_SetPrivate(mJSObject, this);
   NS_ADDREF(this);
   return NS_OK;
 }
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp
+++ b/content/xul/document/src/nsXULPrototypeDocument.cpp
@@ -696,16 +696,21 @@ nsXULPDGlobalObject::EnsureScriptEnviron
   ctxNew->DidInitializeContext();
 
   JSObject* global = ctxNew->GetNativeGlobal();
   NS_ASSERTION(global, "GetNativeGlobal returned NULL!");
 
   mContext = ctxNew;
   mJSObject = global;
 
+  // Set the location information for the new global, so that tools like
+  // about:memory may use that information
+  nsIURI *ownerURI = mGlobalObjectOwner->GetURI();
+  xpc::SetLocationForGlobal(mJSObject, ownerURI);
+
   return NS_OK;
 }
 
 nsIScriptContext*
 nsXULPDGlobalObject::GetScriptContext()
 {
   // This global object creates a context on demand - do that now.
   nsresult rv = EnsureScriptEnvironment();
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1817,17 +1817,19 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
       mInnerWindow = nsnull;
 
       Freeze();
       mCreatingInnerWindow = true;
       // Every script context we are initialized with must create a
       // new global.
       nsCOMPtr<nsIXPConnectJSObjectHolder> &holder = mInnerWindowHolder;
-      rv = mContext->CreateNativeGlobalForInner(sgo, isChrome,
+      rv = mContext->CreateNativeGlobalForInner(sgo,
+                                                aDocument->GetDocumentURI(),
+                                                isChrome,
                                                 aDocument->NodePrincipal(),
                                                 &newInnerWindow->mJSObject,
                                                 getter_AddRefs(holder));
       NS_ASSERTION(NS_SUCCEEDED(rv) && newInnerWindow->mJSObject && holder,
                    "Failed to get script global and holder");
 
       mCreatingInnerWindow = false;
       createdInnerWindow = true;
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -20,16 +20,17 @@ class nsIPrincipal;
 class nsIAtom;
 class nsIArray;
 class nsIVariant;
 class nsIObjectInputStream;
 class nsIObjectOutputStream;
 template<class> class nsScriptObjectHolder;
 class nsIScriptObjectPrincipal;
 class nsIDOMWindow;
+class nsIURI;
 
 typedef void (*nsScriptTerminationFunc)(nsISupports* aRef);
 
 #define NS_ISCRIPTCONTEXTPRINCIPAL_IID \
   { 0xd012cdb3, 0x8f1e, 0x4440, \
     { 0x8c, 0xbd, 0x32, 0x7f, 0x98, 0x1d, 0x37, 0xb4 } }
 
 class nsIScriptContextPrincipal : public nsISupports
@@ -39,18 +40,18 @@ public:
 
   virtual nsIScriptObjectPrincipal* GetObjectPrincipal() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
                               NS_ISCRIPTCONTEXTPRINCIPAL_IID)
 
 #define NS_ISCRIPTCONTEXT_IID \
-{ 0xf1c8c13e, 0xc23b, 0x434e, \
-  { 0xa4, 0x77, 0xe0, 0x2f, 0xc3, 0x73, 0xf8, 0x71 } }
+  { 0xec47ccd4, 0x5f6a, 0x40d6, \
+    { 0xbc, 0x2f, 0x5a, 0x1e, 0xd3, 0xe4, 0xb4, 0xff } }
 
 /* This MUST match JSVERSION_DEFAULT.  This version stuff if we don't
    know what language we have is a little silly... */
 #define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT
 
 /**
  * It is used by the application to initialize a runtime and run scripts.
  * A script runtime would implement this interface.
@@ -260,16 +261,17 @@ public:
 
   /**
    * Create a new global object that will be used for an inner window.
    * Return the native global and an nsISupports 'holder' that can be used
    * to manage the lifetime of it.
    */
   virtual nsresult CreateNativeGlobalForInner(
                                       nsIScriptGlobalObject *aNewInner,
+                                      nsIURI *aURI,
                                       bool aIsChrome,
                                       nsIPrincipal *aPrincipal,
                                       JSObject** aNativeGlobal,
                                       nsISupports **aHolder) = 0;
 
   /**
    * Initialize the context generally. Does not create a global object.
    **/
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2064,16 +2064,17 @@ JSObject*
 nsJSContext::GetNativeGlobal()
 {
     return JS_GetGlobalObject(mContext);
 }
 
 nsresult
 nsJSContext::CreateNativeGlobalForInner(
                                 nsIScriptGlobalObject *aNewInner,
+                                nsIURI *aURI,
                                 bool aIsChrome,
                                 nsIPrincipal *aPrincipal,
                                 JSObject** aNativeGlobal, nsISupports **aHolder)
 {
   nsIXPConnect *xpc = nsContentUtils::XPConnect();
   PRUint32 flags = aIsChrome? nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT : 0;
 
   nsCOMPtr<nsIPrincipal> systemPrincipal;
@@ -2087,16 +2088,22 @@ nsJSContext::CreateNativeGlobalForInner(
           InitClassesWithNewWrappedGlobal(mContext, aNewInner,
                                           aIsChrome ? systemPrincipal.get() : aPrincipal,
                                           flags, getter_AddRefs(jsholder));
   if (NS_FAILED(rv)) {
     return rv;
   }
   jsholder->GetJSObject(aNativeGlobal);
   jsholder.forget(aHolder);
+
+  // Set the location information for the new global, so that tools like
+  // about:memory may use that information
+  MOZ_ASSERT(aNativeGlobal && *aNativeGlobal);
+  xpc::SetLocationForGlobal(*aNativeGlobal, aURI);
+
   return NS_OK;
 }
 
 JSContext*
 nsJSContext::GetNativeContext()
 {
   return xpc_UnmarkGrayContext(mContext);
 }
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -104,16 +104,17 @@ public:
 
   virtual nsIScriptGlobalObject *GetGlobalObject();
   inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; };
 
   virtual JSContext* GetNativeContext();
   virtual JSObject* GetNativeGlobal();
   virtual nsresult CreateNativeGlobalForInner(
                                       nsIScriptGlobalObject *aGlobal,
+                                      nsIURI *aURI,
                                       bool aIsChrome,
                                       nsIPrincipal *aPrincipal,
                                       JSObject** aNativeGlobal,
                                       nsISupports **aHolder);
   virtual nsresult InitContext();
   virtual nsresult InitOuterWindow();
   virtual bool IsContextInitialized();
 
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -564,16 +564,20 @@ mozJSComponentLoader::LoadModule(FileLoc
         fprintf(stderr, "mJCL: couldn't get nsIModule from jsval\n");
 #endif
         return NULL;
     }
 
     // Cache this module for later
     mModules.Put(spec, entry);
 
+    // Set the location information for the new global, so that tools like
+    // about:memory may use that information
+    xpc::SetLocationForGlobal(entry->global, spec);
+
     // The hash owns the ModuleEntry now, forget about it
     return entry.forget();
 }
 
 // Some stack based classes for cleaning up on early return
 #ifdef HAVE_PR_MEMMAP
 class FileAutoCloser
 {
@@ -1121,16 +1125,20 @@ mozJSComponentLoader::ImportInto(const n
                 JS_SetPendingException(callercx, exception.get());
                 return NS_OK;
             }
 
             // Something failed, but we don't know what it is, guess.
             return NS_ERROR_FILE_NOT_FOUND;
         }
 
+        // Set the location information for the new global, so that tools like
+        // about:memory may use that information
+        xpc::SetLocationForGlobal(newEntry->global, aLocation);
+
         mod = newEntry;
     }
 
     NS_ASSERTION(mod->global, "Import table contains entry with no global");
     *_retval = mod->global;
 
     if (targetObj) {
         JSCLContextHelper cxhelper(this);
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3245,19 +3245,19 @@ xpc_CreateSandboxObject(JSContext * cx, 
 
     if (vp) {
         *vp = OBJECT_TO_JSVAL(sandbox);
         if (!WrapForSandbox(cx, wantXrays, vp)) {
             return NS_ERROR_UNEXPECTED;
         }
     }
 
-    xpc::CompartmentPrivate *compartmentPrivate =
-        static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(compartment));
-    compartmentPrivate->location = sandboxName;
+    // Set the location information for the new global, so that tools like
+    // about:memory may use that information
+    xpc::SetLocationForGlobal(sandbox, sandboxName);
 
     return NS_OK;
 }
 
 /* bool call(in nsIXPConnectWrappedNative wrapper,
                in JSContextPtr cx,
                in JSObjectPtr obj,
                in PRUint32 argc,
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1170,21 +1170,22 @@ GetCompartmentName(JSCompartment *c, nsC
         nsJSPrincipals::get(principals)->GetScriptLocation(name);
 
         // If the compartment's location (name) differs from the principal's
         // script location, append the compartment's location to allow
         // differentiation of multiple compartments owned by the same principal
         // (e.g. components owned by the system or null principal).
         xpc::CompartmentPrivate *compartmentPrivate =
             static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(c));
-        if (compartmentPrivate &&
-            !compartmentPrivate->location.IsEmpty() &&
-            !compartmentPrivate->location.Equals(name)) {
-            name.AppendLiteral(", ");
-            name.Append(compartmentPrivate->location);
+        if (compartmentPrivate) {
+            const nsACString& location = compartmentPrivate->GetLocation();
+            if (!location.IsEmpty() && !location.Equals(name)) {
+                name.AppendLiteral(", ");
+                name.Append(location);
+            }
         }
         
         // A hack: replace forward slashes with '\\' so they aren't
         // treated as path separators.  Users of the reporters
         // (such as about:memory) have to undo this change.
         name.ReplaceChar('/', '\\');
     } else {
         name.AssignLiteral("null-principal");
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -2605,16 +2605,46 @@ DumpJSHeap(FILE* file)
     if (!xpc) {
         NS_ERROR("Failed to get nsXPConnect instance!");
         return;
     }
     js::DumpHeapComplete(xpc->GetRuntime()->GetJSRuntime(), file);
 }
 #endif
 
+void
+SetLocationForGlobal(JSObject *global, const nsACString& location)
+{
+    MOZ_ASSERT(global);
+
+    JSCompartment *compartment = js::GetObjectCompartment(global);
+    MOZ_ASSERT(compartment, "No compartment for global");
+
+    xpc::CompartmentPrivate *priv =
+        static_cast<xpc::CompartmentPrivate *>(JS_GetCompartmentPrivate(compartment));
+    MOZ_ASSERT(priv, "No compartment private");
+
+    priv->SetLocation(location);
+}
+
+void
+SetLocationForGlobal(JSObject *global, nsIURI *locationURI)
+{
+    MOZ_ASSERT(global);
+
+    JSCompartment *compartment = js::GetObjectCompartment(global);
+    MOZ_ASSERT(compartment, "No compartment for global");
+
+    xpc::CompartmentPrivate *priv =
+        static_cast<xpc::CompartmentPrivate *>(JS_GetCompartmentPrivate(compartment));
+    MOZ_ASSERT(priv, "No compartment private");
+
+    priv->SetLocation(locationURI);
+}
+
 } // namespace xpc
 
 NS_IMETHODIMP
 nsXPConnect::SetDebugModeWhenPossible(bool mode, bool allowSyncDisable)
 {
     gDesiredDebugMode = mode;
     if (!mode && allowSyncDisable)
         CheckForDebugMode(mRuntime->GetJSRuntime());
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -4337,35 +4337,35 @@ inline JSObject*
 xpc_NewSystemInheritingJSObject(JSContext *cx, JSClass *clasp, JSObject *proto,
                                 bool uniqueType, JSObject *parent);
 
 nsISupports *
 XPC_GetIdentityObject(JSContext *cx, JSObject *obj);
 
 namespace xpc {
 
-struct CompartmentPrivate
+class CompartmentPrivate
 {
+public:
     typedef nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> ExpandoMap;
     typedef nsTHashtable<nsPtrHashKey<JSObject> > DOMExpandoMap;
 
     CompartmentPrivate(bool wantXrays)
         : wantXrays(wantXrays)
     {
         MOZ_COUNT_CTOR(xpc::CompartmentPrivate);
     }
 
     ~CompartmentPrivate();
 
     bool wantXrays;
     nsAutoPtr<JSObject2JSObjectMap> waiverWrapperMap;
     // NB: we don't want this map to hold a strong reference to the wrapper.
     nsAutoPtr<ExpandoMap> expandoMap;
     nsAutoPtr<DOMExpandoMap> domExpandoMap;
-    nsCString location;
 
     bool RegisterExpandoObject(XPCWrappedNative *wn, JSObject *expando) {
         if (!expandoMap) {
             expandoMap = new ExpandoMap();
             expandoMap->Init(8);
         }
         wn->SetHasExpandoObject();
         return expandoMap->Put(wn, expando, mozilla::fallible_t());
@@ -4398,16 +4398,43 @@ struct CompartmentPrivate
             domExpandoMap->Init(8);
         }
         return domExpandoMap->PutEntry(expando, mozilla::fallible_t());
     }
     void RemoveDOMExpandoObject(JSObject *expando) {
         if (domExpandoMap)
             domExpandoMap->RemoveEntry(expando);
     }
+
+    const nsACString& GetLocation() {
+        if (locationURI) {
+            if (NS_FAILED(locationURI->GetSpec(location)))
+                location = NS_LITERAL_CSTRING("<unknown location>");
+            locationURI = nsnull;
+        }
+        return location;
+    }
+    void SetLocation(const nsACString& aLocation) {
+        if (aLocation.IsEmpty())
+            return;
+        if (!location.IsEmpty() || locationURI)
+            return;
+        location = aLocation;
+    }
+    void SetLocation(nsIURI *aLocationURI) {
+        if (!aLocationURI)
+            return;
+        if (!location.IsEmpty() || locationURI)
+            return;
+        locationURI = aLocationURI;
+    }
+
+private:
+    nsCString location;
+    nsCOMPtr<nsIURI> locationURI;
 };
 
 }
 
 /***************************************************************************/
 // Inlines use the above - include last.
 
 #include "XPCInlines.h"
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -224,16 +224,19 @@ bool StringToJsval(JSContext *cx, nsAStr
 bool NonVoidStringToJsval(JSContext *cx, nsAString &str, JS::Value *rval);
 
 nsIPrincipal *GetCompartmentPrincipal(JSCompartment *compartment);
 
 #ifdef DEBUG
 void DumpJSHeap(FILE* file);
 #endif
 
+void SetLocationForGlobal(JSObject *global, const nsACString& location);
+void SetLocationForGlobal(JSObject *global, nsIURI *locationURI);
+
 /**
  * Define quick stubs on the given object, @a proto.
  *
  * @param cx
  *     A context.  Requires request.
  * @param proto
  *     The (newly created) prototype object for a DOM class.  The JS half
  *     of an XPCWrappedNativeProto.