Backed out changeset d4ae1994c20c (bug 1489147) for bustages in JSDebugger.cpp on a CLOSED TREE
authorshindli <shindli@mozilla.com>
Thu, 06 Sep 2018 22:12:44 +0300
changeset 490848 8be67ab3d7d34909c6e52b7e6984b6ff84cc470a
parent 490847 d4ae1994c20c1b0fb9051862606f94e7854b86f2
child 490849 24058c477407069c999e9fdc52d335f54543bbec
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1489147
milestone64.0a1
backs outd4ae1994c20c1b0fb9051862606f94e7854b86f2
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
Backed out changeset d4ae1994c20c (bug 1489147) for bustages in JSDebugger.cpp on a CLOSED TREE
dom/base/nsStructuredCloneContainer.cpp
dom/plugins/base/nsNPAPIPlugin.cpp
extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
ipc/testshell/XPCShellEnvironment.cpp
js/ductwork/debugger/JSDebugger.cpp
js/xpconnect/idl/nsIXPConnect.idl
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCJSID.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCModule.h
js/xpconnect/src/XPCVariant.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
netwerk/base/LoadInfo.cpp
storage/mozStorageConnection.cpp
storage/mozStorageStatementJSHelper.cpp
toolkit/components/places/History.cpp
toolkit/components/places/PlaceInfo.cpp
widget/cocoa/nsMenuX.mm
xpcom/build/Services.py
--- a/dom/base/nsStructuredCloneContainer.cpp
+++ b/dom/base/nsStructuredCloneContainer.cpp
@@ -110,17 +110,17 @@ nsStructuredCloneContainer::DeserializeT
   JS::Rooted<JS::Value> jsStateObj(aCx);
   nsresult rv = DeserializeToJsval(aCx, &jsStateObj);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Now wrap the JS::Value as an nsIVariant.
   nsCOMPtr<nsIVariant> varStateObj;
-  nsCOMPtr<nsIXPConnect> xpconnect = nsIXPConnect::XPConnect();
+  nsCOMPtr<nsIXPConnect> xpconnect = do_GetService(nsIXPConnect::GetCID());
   NS_ENSURE_STATE(xpconnect);
   xpconnect->JSValToVariant(aCx, jsStateObj, getter_AddRefs(varStateObj));
   NS_ENSURE_STATE(varStateObj);
 
   varStateObj.forget(aData);
   return NS_OK;
 }
 
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -729,17 +729,17 @@ NPObject*
   }
 
   dom::AutoJSAPI jsapi;
   if (NS_WARN_IF(!jsapi.Init(doc->GetInnerWindow()))) {
     return nullptr;
   }
   JSContext* cx = jsapi.cx();
 
-  nsCOMPtr<nsIXPConnect> xpc(nsIXPConnect::XPConnect());
+  nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
   NS_ENSURE_TRUE(xpc, nullptr);
 
   JS::RootedValue val(cx);
   if (!ToJSValue(cx, element, &val)) {
     return nullptr;
   }
 
   if (NS_WARN_IF(!val.isObject())) {
--- a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
+++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
@@ -31,34 +31,39 @@ using mozilla::dom::AutoJSAPI;
 //*****************************************************************************
 
 static JS::PersistentRooted<JSObject *> autoconfigSystemSb;
 static JS::PersistentRooted<JSObject *> autoconfigSb;
 static bool sandboxEnabled;
 
 nsresult CentralizedAdminPrefManagerInit(bool aSandboxEnabled)
 {
+    nsresult rv;
+
     // If the sandbox is already created, no need to create it again.
     if (autoconfigSb.initialized())
         return NS_OK;
 
     sandboxEnabled = aSandboxEnabled;
 
     // Grab XPConnect.
-    nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+    nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
+    if (NS_FAILED(rv)) {
+        return rv;
+    }
 
     // Grab the system principal.
     nsCOMPtr<nsIPrincipal> principal;
     nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(principal));
 
 
     // Create a sandbox.
     AutoSafeJSContext cx;
     JS::Rooted<JSObject*> sandbox(cx);
-    nsresult rv = xpc->CreateSandbox(cx, principal, sandbox.address());
+    rv = xpc->CreateSandbox(cx, principal, sandbox.address());
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Unwrap, store and root the sandbox.
     NS_ENSURE_STATE(sandbox);
     autoconfigSystemSb.init(cx, js::UncheckedUnwrap(sandbox));
 
 
     // Create an unprivileged sandbox.
@@ -107,16 +112,18 @@ nsresult EvaluateAdminConfigScript(const
 
 }
 
 nsresult EvaluateAdminConfigScript(JS::HandleObject sandbox,
                                    const char *js_buffer, size_t length,
                                    const char *filename, bool globalContext,
                                    bool callbacks, bool skipFirstLine)
 {
+    nsresult rv = NS_OK;
+
     if (skipFirstLine) {
         /* In order to protect the privacy of the JavaScript preferences file
          * from loading by the browser, we make the first line unparseable
          * by JavaScript. We must skip that line here before executing
          * the JavaScript code.
          */
         unsigned int i = 0;
         while (i < length) {
@@ -130,17 +137,20 @@ nsresult EvaluateAdminConfigScript(JS::H
                 break;
         }
 
         length -= i;
         js_buffer += i;
     }
 
     // Grab XPConnect.
-    nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+    nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
+    if (NS_FAILED(rv)) {
+        return rv;
+    }
 
     AutoJSAPI jsapi;
     if (!jsapi.Init(sandbox)) {
         return NS_ERROR_UNEXPECTED;
     }
     JSContext* cx = jsapi.cx();
 
     nsAutoCString script(js_buffer, length);
@@ -161,15 +171,15 @@ nsresult EvaluateAdminConfigScript(JS::H
     }
     {
         JSAutoRealm ar(cx, autoconfigSystemSb);
         JS::Rooted<JS::Value> value(cx, JS::BooleanValue(isUTF8));
         if (!JS_DefineProperty(cx, autoconfigSystemSb, "gIsUTF8", value, JSPROP_ENUMERATE)) {
             return NS_ERROR_UNEXPECTED;
         }
     }
-    nsresult rv = xpc->EvalInSandboxObject(convertedScript, filename, cx,
+    rv = xpc->EvalInSandboxObject(convertedScript, filename, cx,
                                   sandbox, &v);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return NS_OK;
 }
 
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -195,17 +195,17 @@ DumpXPC(JSContext *cx,
     JS::CallArgs args = CallArgsFromVp(argc, vp);
 
     uint16_t depth = 2;
     if (args.length() > 0) {
         if (!JS::ToUint16(cx, args[0], &depth))
             return false;
     }
 
-    nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+    nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
     if (xpc)
         xpc->DebugDump(int16_t(depth));
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 GC(JSContext *cx,
--- a/js/ductwork/debugger/JSDebugger.cpp
+++ b/js/ductwork/debugger/JSDebugger.cpp
@@ -32,17 +32,18 @@ JSDebugger::JSDebugger()
 
 JSDebugger::~JSDebugger()
 {
 }
 
 NS_IMETHODIMP
 JSDebugger::AddClass(JS::Handle<JS::Value> global, JSContext* cx)
 {
-  nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+  nsresult rv;
+  nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
 
   if (!global.isObject()) {
     return NS_ERROR_INVALID_ARG;
   }
 
   JS::RootedObject obj(cx, &global.toObject());
   obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
   if (!obj) {
--- a/js/xpconnect/idl/nsIXPConnect.idl
+++ b/js/xpconnect/idl/nsIXPConnect.idl
@@ -186,22 +186,29 @@ interface nsIXPConnectWrappedJSUnmarkGra
 interface nsIXPCWrappedJSObjectGetter : nsISupports
 {
     readonly attribute nsISupports neverCalled;
 };
 
 /***************************************************************************/
 
 
-[noscript, builtinclass, uuid(768507b5-b981-40c7-8276-f6a1da502a24)]
+%{ C++
+// For use with the service manager
+// {CB6593E0-F9B2-11d2-BDD6-000064657374}
+#define NS_XPCONNECT_CID \
+{ 0xcb6593e0, 0xf9b2, 0x11d2, \
+    { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
+%}
+
+[noscript, uuid(768507b5-b981-40c7-8276-f6a1da502a24)]
 interface nsIXPConnect : nsISupports
 {
 %{ C++
-    // These get non-addref'd pointers
-    static nsIXPConnect* XPConnect();
+  NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCONNECT_CID)
 %}
 
     /**
     * wrapNative will create a new JSObject or return an existing one.
     *
     * This method now correctly deals with cases where the passed in xpcom
     * object already has an associated JSObject for the cases:
     *  1) The xpcom object has already been wrapped for use in the same scope
@@ -364,11 +371,9 @@ interface nsIXPConnect : nsISupports
                                       in JSContextPtr aJSContext);
 
     [noscript] void writeFunction(in nsIObjectOutputStream aStream,
                                   in JSContextPtr aJSContext,
                                   in JSObjectPtr aJSObject);
 
     [noscript] JSObjectPtr readFunction(in nsIObjectInputStream aStream,
                                         in JSContextPtr aJSContext);
-
-    [infallible] readonly attribute boolean isShuttingDown;
 };
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -64,17 +64,17 @@ JSValIsInterfaceOfType(JSContext* cx, Ha
 {
 
     nsCOMPtr<nsIXPConnectWrappedNative> wn;
     nsCOMPtr<nsISupports> iface;
 
     if (v.isPrimitive())
         return false;
 
-    nsIXPConnect* xpc = nsIXPConnect::XPConnect();
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     RootedObject obj(cx, &v.toObject());
     return NS_SUCCEEDED(xpc->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wn))) && wn &&
         NS_SUCCEEDED(wn->Native()->QueryInterface(iid, getter_AddRefs(iface))) && iface;
 }
 
 char*
 xpc::CloneAllAccess()
 {
@@ -253,17 +253,17 @@ nsXPCComponents_Interfaces::Resolve(nsIX
     if (name && name[0] != '{') {
         const nsXPTInterfaceInfo* info = nsXPTInterfaceInfo::ByName(name.get());
         if (!info)
             return NS_OK;
 
         nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
 
         if (nsid) {
-            nsIXPConnect* xpc = nsIXPConnect::XPConnect();
+            nsXPConnect* xpc = nsXPConnect::XPConnect();
             RootedObject idobj(cx);
             if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
                                              static_cast<nsIJSIID*>(nsid),
                                              NS_GET_IID(nsIJSIID),
                                              idobj.address()))) {
                 if (idobj) {
                     *resolvedp = true;
                     *_retval = JS_DefinePropertyById(cx, obj, id, idobj,
@@ -441,17 +441,17 @@ nsXPCComponents_InterfacesByID::Resolve(
         if (!info)
             return NS_OK;
 
         nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
 
         if (!nsid)
             return NS_ERROR_OUT_OF_MEMORY;
 
-        nsIXPConnect* xpc = nsIXPConnect::XPConnect();
+        nsXPConnect* xpc = nsXPConnect::XPConnect();
         RootedObject idobj(cx);
         if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
                                          static_cast<nsIJSIID*>(nsid),
                                          NS_GET_IID(nsIJSIID),
                                          idobj.address()))) {
             if (idobj) {
                 *resolvedp = true;
                 *_retval =
@@ -626,17 +626,17 @@ nsXPCComponents_Classes::Resolve(nsIXPCo
     if (!JSID_IS_STRING(id))
         return NS_OK;
 
     JS::UniqueChars name = JS_EncodeStringToLatin1(cx, JSID_TO_STRING(id));
     if (name &&
         name[0] != '{') { // we only allow contractids here
         nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.get());
         if (nsid) {
-            nsIXPConnect* xpc = nsIXPConnect::XPConnect();
+            nsXPConnect* xpc = nsXPConnect::XPConnect();
             RootedObject idobj(cx);
             if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
                                              static_cast<nsIJSCID*>(nsid),
                                              NS_GET_IID(nsIJSCID),
                                              idobj.address()))) {
                 if (idobj) {
                     *resolvedp = true;
                     *_retval = JS_DefinePropertyById(cx, obj, id, idobj,
@@ -836,17 +836,17 @@ nsXPCComponents_ClassesByID::Resolve(nsI
 
     RootedString str(cx, JSID_TO_STRING(id));
     JS::UniqueChars name = JS_EncodeStringToLatin1(cx, str);
     if (name && name[0] == '{' &&
         IsRegisteredCLSID(name.get())) // we only allow canonical CLSIDs here
     {
         nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.get());
         if (nsid) {
-            nsIXPConnect* xpc = nsIXPConnect::XPConnect();
+            nsXPConnect* xpc = nsXPConnect::XPConnect();
             RootedObject idobj(cx);
             if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
                                              static_cast<nsIJSCID*>(nsid),
                                              NS_GET_IID(nsIJSCID),
                                              idobj.address()))) {
                 if (idobj) {
                     *resolvedp = true;
                     *_retval = JS_DefinePropertyById(cx, obj, id, idobj,
@@ -1315,17 +1315,17 @@ nsXPCComponents_Exception::Construct(nsI
 {
     RootedObject obj(cx, objArg);
     return CallOrConstruct(wrapper, cx, obj, args, _retval);
 }
 
 struct MOZ_STACK_CLASS ExceptionArgParser
 {
     ExceptionArgParser(JSContext* context,
-                       nsIXPConnect* xpconnect)
+                       nsXPConnect* xpconnect)
         : eMsg("exception")
         , eResult(NS_ERROR_FAILURE)
         , cx(context)
         , xpc(xpconnect)
     {}
 
     // Public exception parameter values. During construction, these are
     // initialized to the appropriate defaults.
@@ -1459,26 +1459,26 @@ struct MOZ_STACK_CLASS ExceptionArgParse
      * Internal data members.
      */
 
     // If there's a non-default exception string, hold onto the allocated bytes.
     JS::UniqueChars messageBytes;
 
     // Various bits and pieces that are helpful to have around.
     JSContext* cx;
-    nsIXPConnect* xpc;
+    nsXPConnect* xpc;
 };
 
 // static
 nsresult
 nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,
                                            JSContext* cx, HandleObject obj,
                                            const CallArgs& args, bool* _retval)
 {
-    nsIXPConnect* xpc = nsIXPConnect::XPConnect();
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
 
     MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::IsCallerChrome());
 
     // Parse the arguments to the Exception constructor.
     ExceptionArgParser parser(cx, xpc);
     if (!parser.parse(args))
         return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
 
@@ -1677,17 +1677,17 @@ nsXPCConstructor::Construct(nsIXPConnect
     return CallOrConstruct(wrapper, cx, obj, args, _retval);
 }
 
 // static
 nsresult
 nsXPCConstructor::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,JSContext* cx,
                                   HandleObject obj, const CallArgs& args, bool* _retval)
 {
-    nsIXPConnect* xpc = nsIXPConnect::XPConnect();
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
 
     // security check not required because we are going to call through the
     // code which is reflected into JS which will do that for us later.
 
     RootedObject cidObj(cx);
     RootedObject iidObj(cx);
 
     if (NS_FAILED(xpc->WrapNative(cx, obj, mClassID, NS_GET_IID(nsIJSCID), cidObj.address())) || !cidObj ||
@@ -1854,17 +1854,17 @@ nsXPCComponents_Constructor::CallOrConst
 {
     // make sure we have at least one arg
 
     if (args.length() < 1)
         return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
 
     // get the various other object pointers we need
 
-    nsIXPConnect* xpc = nsIXPConnect::XPConnect();
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     XPCWrappedNativeScope* scope = ObjectScope(obj);
     nsCOMPtr<nsIXPCComponents> comp;
 
     if (!xpc || !scope || !(comp = do_QueryInterface(scope->GetComponents())))
         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
 
     // Do the security check if necessary
 
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -753,17 +753,17 @@ nsJSCID::HasInstance(nsIXPConnectWrapped
 
 JSObject*
 xpc_NewIDObject(JSContext* cx, HandleObject scope, const nsID& aID)
 {
     RootedObject obj(cx);
 
     nsCOMPtr<nsIJSID> iid = nsJSID::NewID(aID);
     if (iid) {
-        nsIXPConnect* xpc = nsIXPConnect::XPConnect();
+        nsXPConnect* xpc = nsXPConnect::XPConnect();
         if (xpc) {
             xpc->WrapNative(cx, scope, static_cast<nsISupports*>(iid),
                             NS_GET_IID(nsIJSID), obj.address());
         }
     }
     return obj;
 }
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -672,17 +672,17 @@ bool XPCJSRuntime::UsefulToMergeZones() 
 void XPCJSRuntime::TraceNativeBlackRoots(JSTracer* trc)
 {
     for (CycleCollectedJSContext* ccx : Contexts()) {
         auto* cx = static_cast<const XPCJSContext*>(ccx);
         if (AutoMarkingPtr* roots = cx->mAutoRoots)
             roots->TraceJSAll(trc);
     }
 
-    dom::TraceBlackJS(trc, nsIXPConnect::XPConnect()->GetIsShuttingDown());
+    dom::TraceBlackJS(trc, nsXPConnect::XPConnect()->IsShuttingDown());
 }
 
 void XPCJSRuntime::TraceAdditionalNativeGrayRoots(JSTracer* trc)
 {
     XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(trc);
 
     for (XPCRootSetElem* e = mVariantRoots; e ; e = e->GetNextRoot())
         static_cast<XPCTraceableVariant*>(e)->TraceJS(trc);
--- a/js/xpconnect/src/XPCModule.h
+++ b/js/xpconnect/src/XPCModule.h
@@ -16,31 +16,36 @@
 // {FE4F7592-C1FC-4662-AC83-538841318803}
 #define SCRIPTABLE_INTERFACES_CID                                             \
     {0xfe4f7592, 0xc1fc, 0x4662,                                              \
       { 0xac, 0x83, 0x53, 0x88, 0x41, 0x31, 0x88, 0x3 } }
 
 #define MOZJSSUBSCRIPTLOADER_CONTRACTID "@mozilla.org/moz/jssubscript-loader;1"
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSID)
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIXPConnect,
+                                         nsXPConnect::GetSingleton)
 
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(mozJSComponentLoader,
                                          mozJSComponentLoader::GetOrCreate);
 NS_GENERIC_FACTORY_CONSTRUCTOR(mozJSSubScriptLoader)
 
 NS_DEFINE_NAMED_CID(NS_JS_ID_CID);
+NS_DEFINE_NAMED_CID(NS_XPCONNECT_CID);
 NS_DEFINE_NAMED_CID(MOZJSCOMPONENTLOADER_CID);
 NS_DEFINE_NAMED_CID(MOZ_JSSUBSCRIPTLOADER_CID);
 
 #define XPCONNECT_CIDENTRIES                                                  \
   { &kNS_JS_ID_CID, false, nullptr,  nsJSIDConstructor },                     \
+  { &kNS_XPCONNECT_CID, false, nullptr,  nsIXPConnectConstructor },           \
   { &kMOZJSCOMPONENTLOADER_CID, false, nullptr, mozJSComponentLoaderConstructor },\
   { &kMOZ_JSSUBSCRIPTLOADER_CID, false, nullptr, mozJSSubScriptLoaderConstructor },
 
 #define XPCONNECT_CONTRACTS                                                   \
+  { XPC_XPCONNECT_CONTRACTID, &kNS_XPCONNECT_CID },                           \
   { MOZJSCOMPONENTLOADER_CONTRACTID, &kMOZJSCOMPONENTLOADER_CID },            \
   { MOZJSSUBSCRIPTLOADER_CONTRACTID, &kMOZ_JSSUBSCRIPTLOADER_CID },
 
 #define XPCONNECT_CATEGORIES \
   { "module-loader", "js", MOZJSCOMPONENTLOADER_CONTRACTID },
 
 nsresult xpcModuleCtor();
 void xpcModuleDtor();
--- a/js/xpconnect/src/XPCVariant.cpp
+++ b/js/xpconnect/src/XPCVariant.cpp
@@ -350,17 +350,17 @@ bool XPCVariant::InitializeData(JSContex
         mData.u.array.mArrayCount = len;
         mData.u.array.mArrayType = elty.Tag();
 
         return true;
     }
 
     // XXX This could be smarter and pick some more interesting iface.
 
-    nsIXPConnect* xpc = nsIXPConnect::XPConnect();
+    nsXPConnect*  xpc = nsXPConnect::XPConnect();
     nsCOMPtr<nsISupports> wrapper;
     const nsIID& iid = NS_GET_IID(nsISupports);
 
     if (NS_FAILED(xpc->WrapJS(cx, jsobj, iid, getter_AddRefs(wrapper)))) {
         return false;
     }
 
     mData.SetFromInterface(iid, wrapper);
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -6,16 +6,17 @@
 
 /* High level class and public functions implementation. */
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Base64.h"
 #include "mozilla/Likely.h"
 #include "mozilla/Unused.h"
 
+#include "xpcprivate.h"
 #include "XPCWrapper.h"
 #include "jsfriendapi.h"
 #include "js/ProfilingStack.h"
 #include "GeckoProfiler.h"
 #include "nsJSEnvironment.h"
 #include "nsThreadUtils.h"
 #include "nsDOMJSUtils.h"
 
@@ -53,16 +54,17 @@ bool         nsXPConnect::gOnceAliveNowD
 // Global cache of the default script security manager (QI'd to
 // nsIScriptSecurityManager) and the system principal.
 nsIScriptSecurityManager* nsXPConnect::gScriptSecurityManager = nullptr;
 nsIPrincipal* nsXPConnect::gSystemPrincipal = nullptr;
 
 const char XPC_EXCEPTION_CONTRACTID[]     = "@mozilla.org/js/xpc/Exception;1";
 const char XPC_CONSOLE_CONTRACTID[]       = "@mozilla.org/consoleservice;1";
 const char XPC_SCRIPT_ERROR_CONTRACTID[]  = "@mozilla.org/scripterror;1";
+const char XPC_XPCONNECT_CONTRACTID[]     = "@mozilla.org/js/xpc/XPConnect;1";
 
 /***************************************************************************/
 
 // This global should be used very sparingly: only to create and destroy
 // nsXPConnect and when creating a new cooperative (non-primary) XPCJSContext.
 static XPCJSContext* gPrimaryContext;
 
 nsXPConnect::nsXPConnect()
@@ -147,16 +149,22 @@ nsXPConnect::InitStatics()
         MOZ_CRASH("InitSelfHostedCode failed");
     if (!gSelf->mRuntime->InitializeStrings(cx))
         MOZ_CRASH("InitializeStrings failed");
 
     // Initialize our singleton scopes.
     gSelf->mRuntime->InitSingletonScopes();
 }
 
+already_AddRefed<nsXPConnect>
+nsXPConnect::GetSingleton()
+{
+    return do_AddRef(nsXPConnect::XPConnect());
+}
+
 // static
 void
 nsXPConnect::ReleaseXPConnectSingleton()
 {
     nsXPConnect* xpc = gSelf;
     if (xpc) {
         nsrefcnt cnt;
         NS_RELEASE2(xpc, cnt);
@@ -1085,40 +1093,16 @@ nsXPConnect::WriteFunction(nsIObjectOutp
 }
 
 NS_IMETHODIMP
 nsXPConnect::ReadFunction(nsIObjectInputStream* stream, JSContext* cx, JSObject** functionObjp)
 {
     return ReadScriptOrFunction(stream, cx, nullptr, functionObjp);
 }
 
-NS_IMETHODIMP
-nsXPConnect::GetIsShuttingDown(bool* aIsShuttingDown)
-{
-    if (!aIsShuttingDown)
-        return NS_ERROR_INVALID_ARG;
-
-    *aIsShuttingDown = mShuttingDown;
-
-    return NS_OK;
-}
-
-// static
-nsIXPConnect*
-nsIXPConnect::XPConnect()
-{
-    // Do a release-mode assert that we're not doing anything significant in
-    // XPConnect off the main thread. If you're an extension developer hitting
-    // this, you need to change your code. See bug 716167.
-    if (!MOZ_LIKELY(NS_IsMainThread()))
-        MOZ_CRASH();
-
-    return nsXPConnect::gSelf;
-}
-
 /* These are here to be callable from a debugger */
 extern "C" {
 
 MOZ_EXPORT void
 DumpJSStack()
 {
     xpc_DumpJSStack(true, true, false);
 }
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -224,16 +224,28 @@ class nsXPConnect final : public nsIXPCo
 {
 public:
     // all the interface method declarations...
     NS_DECL_ISUPPORTS
     NS_DECL_NSIXPCONNECT
 
     // non-interface implementation
 public:
+    // These get non-addref'd pointers
+    static nsXPConnect* XPConnect()
+    {
+        // Do a release-mode assert that we're not doing anything significant in
+        // XPConnect off the main thread. If you're an extension developer hitting
+        // this, you need to change your code. See bug 716167.
+        if (!MOZ_LIKELY(NS_IsMainThread()))
+            MOZ_CRASH();
+
+        return gSelf;
+    }
+
     static XPCJSRuntime* GetRuntimeInstance();
 
     static bool IsISupportsDescendant(const nsXPTInterfaceInfo* info);
 
     static nsIScriptSecurityManager* SecurityManager()
     {
         MOZ_ASSERT(NS_IsMainThread());
         MOZ_ASSERT(gScriptSecurityManager);
@@ -242,44 +254,45 @@ public:
 
     static nsIPrincipal* SystemPrincipal()
     {
         MOZ_ASSERT(NS_IsMainThread());
         MOZ_ASSERT(gSystemPrincipal);
         return gSystemPrincipal;
     }
 
+    static already_AddRefed<nsXPConnect> GetSingleton();
+
     // Called by module code in dll startup
     static void InitStatics();
     // Called by module code on dll shutdown.
     static void ReleaseXPConnectSingleton();
 
+    bool IsShuttingDown() const {return mShuttingDown;}
+
     void RecordTraversal(void* p, nsISupports* s);
 
 protected:
     virtual ~nsXPConnect();
 
     nsXPConnect();
 
 private:
     // Singleton instance
     static nsXPConnect*             gSelf;
     static bool                     gOnceAliveNowDead;
 
     XPCJSRuntime*                   mRuntime;
     bool                            mShuttingDown;
 
-    friend class nsIXPConnect;
-
 public:
     static nsIScriptSecurityManager* gScriptSecurityManager;
     static nsIPrincipal* gSystemPrincipal;
 };
 
-
 /***************************************************************************/
 
 class XPCRootSetElem
 {
 public:
     XPCRootSetElem() :
         mNext(nullptr),
         mSelfp(nullptr)
@@ -756,17 +769,17 @@ private:
 inline void CHECK_STATE(int s) const {MOZ_ASSERT(mState >= s, "bad state");}
 #else
 #define CHECK_STATE(s) ((void)0)
 #endif
 
 private:
     State                           mState;
 
-    nsCOMPtr<nsIXPConnect>          mXPC;
+    RefPtr<nsXPConnect>           mXPC;
 
     XPCJSContext*                   mXPCJSContext;
     JSContext*                      mJSContext;
 
     // ctor does not necessarily init the following. BEWARE!
 
     XPCCallContext*                 mPrevCallContext;
 
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -17,17 +17,16 @@
 #include "nsFrameLoader.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
 #include "nsIFrameLoaderOwner.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsISupportsImpl.h"
 #include "nsISupportsUtils.h"
-#include "nsIXPConnect.h"
 #include "nsContentUtils.h"
 #include "nsDocShell.h"
 #include "nsGlobalWindow.h"
 #include "nsMixedContentBlocker.h"
 #include "nsRedirectHistoryEntry.h"
 #include "LoadInfo.h"
 
 using namespace mozilla::dom;
@@ -1168,17 +1167,17 @@ LoadInfo::GetRedirects(JSContext* aCx, J
                        const RedirectHistoryArray& aArray)
 {
   JS::Rooted<JSObject*> redirects(aCx, JS_NewArrayObject(aCx, aArray.Length()));
   NS_ENSURE_TRUE(redirects, NS_ERROR_OUT_OF_MEMORY);
 
   JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
   NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
 
-  nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+  nsCOMPtr<nsIXPConnect> xpc = mozilla::services::GetXPConnect();
 
   for (size_t idx = 0; idx < aArray.Length(); idx++) {
     JS::RootedObject jsobj(aCx);
     nsresult rv = xpc->WrapNative(aCx, global, aArray[idx],
                                   NS_GET_IID(nsIRedirectHistoryEntry),
                                   jsobj.address());
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_STATE(jsobj);
--- a/storage/mozStorageConnection.cpp
+++ b/storage/mozStorageConnection.cpp
@@ -1336,17 +1336,17 @@ Connection::Close()
 #endif // DEBUG
 
   // Make sure we have not executed any asynchronous statements.
   // If this fails, the mDBConn may be left open, resulting in a leak.
   // We'll try to finalize the pending statements and close the connection.
   if (isAsyncExecutionThreadAvailable()) {
 #ifdef DEBUG
     if (NS_IsMainThread()) {
-      nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+      nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
       Unused << xpc->DebugDumpJSStack(false, false, false);
     }
 #endif
     MOZ_ASSERT(false,
                "Close() was invoked on a connection that executed asynchronous statements. "
                "Should have used asyncClose().");
     // Try to close the database regardless, to free up resources.
     Unused << SpinningSynchronousClose();
--- a/storage/mozStorageStatementJSHelper.cpp
+++ b/storage/mozStorageStatementJSHelper.cpp
@@ -30,17 +30,17 @@ namespace storage {
 //// Global Functions
 
 static
 bool
 stepFunc(JSContext *aCtx, uint32_t argc, JS::Value *_vp)
 {
   JS::CallArgs args = CallArgsFromVp(argc, _vp);
 
-  nsCOMPtr<nsIXPConnect> xpc(nsIXPConnect::XPConnect());
+  nsCOMPtr<nsIXPConnect> xpc(mozilla::services::GetXPConnect());
   nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
 
   if (!args.thisv().isObject()) {
     ::JS_ReportErrorASCII(aCtx, "mozIStorageStatement::step() requires object");
     return false;
   }
 
   JSObject *obj = &args.thisv().toObject();
--- a/toolkit/components/places/History.cpp
+++ b/toolkit/components/places/History.cpp
@@ -223,17 +223,17 @@ GetJSArrayFromJSValue(JS::Handle<JS::Val
  * @param aValue
  *        The JS value to convert.
  * @return the nsIURI object, or null if aValue is not a nsIURI object.
  */
 already_AddRefed<nsIURI>
 GetJSValueAsURI(JSContext* aCtx,
                 const JS::Value& aValue) {
   if (!aValue.isPrimitive()) {
-    nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+    nsCOMPtr<nsIXPConnect> xpc = mozilla::services::GetXPConnect();
 
     nsCOMPtr<nsIXPConnectWrappedNative> wrappedObj;
     nsresult rv = xpc->GetWrappedNativeOfJSObject(aCtx, aValue.toObjectOrNull(),
                                                   getter_AddRefs(wrappedObj));
     NS_ENSURE_SUCCESS(rv, nullptr);
     nsCOMPtr<nsIURI> uri = do_QueryWrappedNative(wrappedObj);
     return uri.forget();
   }
@@ -2516,17 +2516,17 @@ History::UpdatePlaces(JS::Handle<JS::Val
       NS_ENSURE_SUCCESS(rv, rv);
       // visitDate should be in microseconds. It's easy to do the wrong thing
       // and pass milliseconds to updatePlaces, so we lazily check for that.
       // While it's not easily distinguishable, since both are integers, we can
       // check if the value is very far in the past, and assume it's probably
       // a mistake.
       if (data.visitTime < (PR_Now() / 1000)) {
 #ifdef DEBUG
-        nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+        nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
         Unused << xpc->DebugDumpJSStack(false, false, false);
         MOZ_CRASH("invalid time format passed to updatePlaces");
 #endif
         return NS_ERROR_INVALID_ARG;
       }
       uint32_t transitionType = 0;
       rv = GetIntFromJSObject(aCtx, visit, "transitionType", &transitionType);
       NS_ENSURE_SUCCESS(rv, rv);
--- a/toolkit/components/places/PlaceInfo.cpp
+++ b/toolkit/components/places/PlaceInfo.cpp
@@ -102,17 +102,17 @@ PlaceInfo::GetVisits(JSContext* aContext
   // visit here, we will likely want to make this cache the value.
   JS::Rooted<JSObject*> visits(aContext,
                                JS_NewArrayObject(aContext, 0));
   NS_ENSURE_TRUE(visits, NS_ERROR_OUT_OF_MEMORY);
 
   JS::Rooted<JSObject*> global(aContext, JS::CurrentGlobalOrNull(aContext));
   NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
 
-  nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+  nsCOMPtr<nsIXPConnect> xpc = mozilla::services::GetXPConnect();
 
   for (VisitsArray::size_type idx = 0; idx < mVisits.Length(); idx++) {
     JS::RootedObject jsobj(aContext);
     nsresult rv = xpc->WrapNative(aContext, global, mVisits[idx],
                                   NS_GET_IID(mozIVisitInfo),
                                   jsobj.address());
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_STATE(jsobj);
--- a/widget/cocoa/nsMenuX.mm
+++ b/widget/cocoa/nsMenuX.mm
@@ -414,25 +414,29 @@ void nsMenuX::MenuConstruct()
   GetMenuPopupContent(getter_AddRefs(menuPopup));
   if (!menuPopup) {
     gConstructingMenu = false;
     return;
   }
 
   // bug 365405: Manually wrap the menupopup node to make sure it's bounded
   if (!mXBLAttached) {
-    nsCOMPtr<nsIXPConnect> xpconnect = nsIXPConnect::XPConnect();
-    nsIDocument* ownerDoc = menuPopup->OwnerDoc();
-    dom::AutoJSAPI jsapi;
-    if (ownerDoc && jsapi.Init(ownerDoc->GetInnerWindow())) {
-      JSContext* cx = jsapi.cx();
-      JS::RootedObject ignoredObj(cx);
-      xpconnect->WrapNative(cx, JS::CurrentGlobalOrNull(cx), menuPopup,
-                            NS_GET_IID(nsISupports), ignoredObj.address());
-      mXBLAttached = true;
+    nsresult rv;
+    nsCOMPtr<nsIXPConnect> xpconnect =
+      do_GetService(nsIXPConnect::GetCID(), &rv);
+    if (NS_SUCCEEDED(rv)) {
+      nsIDocument* ownerDoc = menuPopup->OwnerDoc();
+      dom::AutoJSAPI jsapi;
+      if (ownerDoc && jsapi.Init(ownerDoc->GetInnerWindow())) {
+        JSContext* cx = jsapi.cx();
+        JS::RootedObject ignoredObj(cx);
+        xpconnect->WrapNative(cx, JS::CurrentGlobalOrNull(cx), menuPopup,
+                              NS_GET_IID(nsISupports), ignoredObj.address());
+        mXBLAttached = true;
+      }
     }
   }
 
   // Iterate over the kids
   for (nsIContent* child = menuPopup->GetFirstChild();
        child; child = child->GetNextSibling()) {
     // depending on the type, create a menu item, separator, or submenu
     if (child->IsAnyOfXULElements(nsGkAtoms::menuitem,
--- a/xpcom/build/Services.py
+++ b/xpcom/build/Services.py
@@ -15,16 +15,18 @@ service('ToolkitChromeRegistryService', 
 service('XULChromeRegistryService', 'nsIXULChromeRegistry',
         "@mozilla.org/chrome/chrome-registry;1")
 service('IOService', 'nsIIOService',
         "@mozilla.org/network/io-service;1")
 service('ObserverService', 'nsIObserverService',
         "@mozilla.org/observer-service;1")
 service('StringBundleService', 'nsIStringBundleService',
         "@mozilla.org/intl/stringbundle;1")
+service('XPConnect', 'nsIXPConnect',
+        "@mozilla.org/js/xpc/XPConnect;1")
 service('PermissionManager', 'nsIPermissionManager',
         "@mozilla.org/permissionmanager;1")
 service('ServiceWorkerManager', 'nsIServiceWorkerManager',
         "@mozilla.org/serviceworkers/manager;1")
 service('AsyncShutdown', 'nsIAsyncShutdownService',
         "@mozilla.org/async-shutdown-service;1")
 service('UUIDGenerator', 'nsIUUIDGenerator',
         "@mozilla.org/uuid-generator;1")