Bug 929120 - Add a way to get compartment locations ignoring non-addon locations. r=njn
authorNils Maier <maierman@web.de>
Thu, 31 Oct 2013 23:04:11 -0400
changeset 167548 eac93c93b680d48726a0231b5b17daa6b378cf61
parent 167547 f1b840b5717d56187793c2a3e46b1bedd5651a47
child 167549 ed35c291d57ed85b5394775e163aeb8d96f6b1ee
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs929120
milestone28.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 929120 - Add a way to get compartment locations ignoring non-addon locations. r=njn Use that new way to map compartments to add-ons. As an added bonus, fix a currently unproblematic off-by-one error in the location parser.
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/xpcprivate.h
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -284,22 +284,56 @@ CompartmentPrivate::~CompartmentPrivate(
     MOZ_COUNT_DTOR(xpc::CompartmentPrivate);
 
     Telemetry::Accumulate(Telemetry::COMPARTMENT_ADOPTED_NODE, adoptedNode);
     Telemetry::Accumulate(Telemetry::COMPARTMENT_DONATED_NODE, donatedNode);
     if (adoptedNode)
         --kLivingAdopters;
 }
 
-bool CompartmentPrivate::TryParseLocationURI()
+static bool
+TryParseLocationURICandidate(const nsACString& uristr,
+                             CompartmentPrivate::LocationHint aLocationHint,
+                             nsIURI** aURI)
 {
-    // Already tried parsing the location before
-    if (locationWasParsed)
-      return false;
-    locationWasParsed = true;
+    static NS_NAMED_LITERAL_CSTRING(kGRE, "resource://gre/");
+    static NS_NAMED_LITERAL_CSTRING(kToolkit, "chrome://global/");
+    static NS_NAMED_LITERAL_CSTRING(kBrowser, "chrome://browser/");
+
+    if (aLocationHint == CompartmentPrivate::LocationHintAddon) {
+        // Blacklist some known locations which are clearly not add-on related.
+        if (StringBeginsWith(uristr, kGRE) ||
+            StringBeginsWith(uristr, kToolkit) ||
+            StringBeginsWith(uristr, kBrowser))
+            return false;
+    }
+
+    nsCOMPtr<nsIURI> uri;
+    if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), uristr)))
+        return false;
+
+    nsAutoCString scheme;
+    if (NS_FAILED(uri->GetScheme(scheme)))
+        return false;
+
+    // Cannot really map data: and blob:.
+    // Also, data: URIs are pretty memory hungry, which is kinda bad
+    // for memory reporter use.
+    if (scheme.EqualsLiteral("data") || scheme.EqualsLiteral("blob"))
+        return false;
+
+    uri.forget(aURI);
+    return true;
+}
+
+bool CompartmentPrivate::TryParseLocationURI(CompartmentPrivate::LocationHint aLocationHint,
+                                             nsIURI **aURI)
+{
+    if (!aURI)
+        return false;
 
     // Need to parse the URI.
     if (location.IsEmpty())
         return false;
 
     // Handle Sandbox location strings.
     // A sandbox string looks like this:
     // <sandboxName> (from: <js-stack-frame-filename>:<lineno>)
@@ -315,22 +349,23 @@ bool CompartmentPrivate::TryParseLocatio
     static const nsDependentCString from("(from: ");
     static const nsDependentCString arrow(" -> ");
     static const size_t fromLength = from.Length();
     static const size_t arrowLength = arrow.Length();
 
     // See: XPCComponents.cpp#AssembleSandboxMemoryReporterName
     int32_t idx = location.Find(from);
     if (idx < 0)
-        return TryParseLocationURICandidate(location);
+        return TryParseLocationURICandidate(location, aLocationHint, aURI);
 
 
     // When parsing we're looking for the right-most URI. This URI may be in
     // <sandboxName>, so we try this first.
-    if (TryParseLocationURICandidate(Substring(location, 0, idx)))
+    if (TryParseLocationURICandidate(Substring(location, 0, idx), aLocationHint,
+                                     aURI))
         return true;
 
     // Not in <sandboxName> so we need to inspect <js-stack-frame-filename> and
     // the chain that is potentially contained within and grab the rightmost
     // item that is actually a URI.
 
     // First, hack off the :<lineno>) part as well
     int32_t ridx = location.RFind(NS_LITERAL_CSTRING(":"));
@@ -338,52 +373,31 @@ bool CompartmentPrivate::TryParseLocatio
                                   ridx - idx - fromLength));
 
     // Loop over the "->" chain. This loop also works for non-chains, or more
     // correctly chains with only one item.
     for (;;) {
         idx = chain.RFind(arrow);
         if (idx < 0) {
             // This is the last chain item. Try to parse what is left.
-            return TryParseLocationURICandidate(chain);
+            return TryParseLocationURICandidate(chain, aLocationHint, aURI);
         }
 
         // Try to parse current chain item
-        if (TryParseLocationURICandidate(Substring(chain, idx + arrowLength)))
+        if (TryParseLocationURICandidate(Substring(chain, idx + arrowLength),
+                                         aLocationHint, aURI))
             return true;
 
         // Current chain item couldn't be parsed.
-        // Don't forget whitespace in " -> "
-        idx -= 1;
-        // Strip current item and continue
+        // Strip current item and continue.
         chain = Substring(chain, 0, idx);
     }
     MOZ_ASSUME_UNREACHABLE("Chain parser loop does not terminate");
 }
 
-bool CompartmentPrivate::TryParseLocationURICandidate(const nsACString& uristr)
-{
-    nsCOMPtr<nsIURI> uri;
-    if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), uristr)))
-        return false;
-
-    nsAutoCString scheme;
-    if (NS_FAILED(uri->GetScheme(scheme)))
-        return false;
-
-    // Cannot really map data: and blob:.
-    // Also, data: URIs are pretty memory hungry, which is kinda bad
-    // for memory reporter use.
-    if (scheme.EqualsLiteral("data") || scheme.EqualsLiteral("blob"))
-        return false;
-
-    locationURI = uri.forget();
-    return true;
-}
-
 CompartmentPrivate*
 EnsureCompartmentPrivate(JSObject *obj)
 {
     return EnsureCompartmentPrivate(js::GetObjectCompartment(obj));
 }
 
 CompartmentPrivate*
 EnsureCompartmentPrivate(JSCompartment *c)
@@ -2529,17 +2543,18 @@ class XPCJSRuntimeStats : public JS::Run
                                            JS::CompartmentStats *cstats) MOZ_OVERRIDE
     {
         xpc::CompartmentStatsExtras *extras = new xpc::CompartmentStatsExtras;
         nsCString cName;
         GetCompartmentName(c, cName, true);
         if (mGetLocations) {
             CompartmentPrivate *cp = GetCompartmentPrivate(c);
             if (cp)
-              cp->GetLocationURI(getter_AddRefs(extras->location));
+              cp->GetLocationURI(CompartmentPrivate::LocationHintAddon,
+                                 getter_AddRefs(extras->location));
             // Note: cannot use amIAddonManager implementation at this point,
             // as it is a JS service and the JS heap is currently not idle.
             // Otherwise, we could have computed the add-on id at this point.
         }
 
         // Get the compartment's global.
         nsXPConnect *xpc = nsXPConnect::XPConnect();
         AutoSafeJSContext cx;
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3736,23 +3736,27 @@ xpc_ForcePropertyResolve(JSContext* cx, 
 inline jsid
 GetRTIdByIndex(JSContext *cx, unsigned index);
 
 namespace xpc {
 
 class CompartmentPrivate
 {
 public:
+    enum LocationHint {
+        LocationHintRegular,
+        LocationHintAddon
+    };
+
     CompartmentPrivate()
         : wantXrays(false)
         , universalXPConnectEnabled(false)
         , adoptedNode(false)
         , donatedNode(false)
         , scope(nullptr)
-        , locationWasParsed(false)
     {
         MOZ_COUNT_CTOR(xpc::CompartmentPrivate);
     }
 
     ~CompartmentPrivate();
 
     bool wantXrays;
 
@@ -3773,20 +3777,24 @@ public:
     const nsACString& GetLocation() {
         if (location.IsEmpty() && locationURI) {
             if (NS_FAILED(locationURI->GetSpec(location)))
                 location = NS_LITERAL_CSTRING("<unknown location>");
         }
         return location;
     }
     bool GetLocationURI(nsIURI **aURI) {
-        if (!locationURI && !TryParseLocationURI())
-            return false;
-        NS_IF_ADDREF(*aURI = locationURI);
-        return true;
+        return GetLocationURI(LocationHintRegular, aURI);
+    }
+    bool GetLocationURI(LocationHint aLocationHint, nsIURI **aURI) {
+        if (locationURI) {
+            NS_IF_ADDREF(*aURI = locationURI);
+            return true;
+        }
+        return TryParseLocationURI(aLocationHint, aURI);
     }
     void SetLocation(const nsACString& aLocation) {
         if (aLocation.IsEmpty())
             return;
         if (!location.IsEmpty() || locationURI)
             return;
         location = aLocation;
     }
@@ -3796,20 +3804,18 @@ public:
         if (locationURI)
             return;
         locationURI = aLocationURI;
     }
 
 private:
     nsCString location;
     nsCOMPtr<nsIURI> locationURI;
-    bool locationWasParsed;
-
-    bool TryParseLocationURI();
-    bool TryParseLocationURICandidate(const nsACString& uristr);
+
+    bool TryParseLocationURI(LocationHint aType, nsIURI** aURI);
 };
 
 CompartmentPrivate*
 EnsureCompartmentPrivate(JSObject *obj);
 
 CompartmentPrivate*
 EnsureCompartmentPrivate(JSCompartment *c);