# This Source Code Form is subject to the terms of the Mozilla Public # 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/. # NOTE: Although this generates headers and code for C++, using Services.h # is deprecated in favour of Components.h. services = [] def service(name, iface, contractid): """Define a convenient service getter""" services.append((name, iface, contractid)) # The `name` parameter is derived from the `iface` by removing the `nsI` # prefix. (This often matches the `contractid`, but not always.) service("ChromeRegistry", "nsIChromeRegistry", "@mozilla.org/chrome/chrome-registry;1") service("IOService", "nsIIOService", "@mozilla.org/network/io-service;1") service("ObserverService", "nsIObserverService", "@mozilla.org/observer-service;1") service("PermissionManager", "nsIPermissionManager", "@mozilla.org/permissionmanager;1") service( "AsyncShutdownService", "nsIAsyncShutdownService", "@mozilla.org/async-shutdown-service;1", ) # The definition file needs access to the definitions of the particular # interfaces. If you add a new interface here, make sure the necessary includes # are also listed in the following code snippet. CPP_INCLUDES = """ #include "mozilla/Likely.h" #include "mozilla/Services.h" #include "mozIThirdPartyUtil.h" #include "nsComponentManager.h" #include "nsIObserverService.h" #include "nsNetCID.h" #include "nsObserverService.h" #include "nsXPCOMPrivate.h" #include "nsIIOService.h" #include "nsIDirectoryService.h" #include "nsIChromeRegistry.h" #include "nsIStringBundle.h" #include "nsIToolkitChromeRegistry.h" #include "IHistory.h" #include "nsIXPConnect.h" #include "nsIPermissionManager.h" #include "nsIPrefService.h" #include "nsIServiceWorkerManager.h" #include "nsICacheStorageService.h" #include "nsIStreamTransportService.h" #include "nsISocketTransportService.h" #include "nsIURIClassifier.h" #include "nsIHttpActivityObserver.h" #include "nsIAsyncShutdown.h" #include "nsIUUIDGenerator.h" #include "nsIGfxInfo.h" #include "nsIURIFixup.h" #include "nsIBits.h" #include "nsIXULRuntime.h" """ ##### # Codegen Logic # # The following code consumes the data listed above to generate the files # Services.h, and Services.cpp which provide access to these service getters in # C++ code. def services_h(output): output.write( """\ /* THIS FILE IS GENERATED BY Services.py - DO NOT EDIT */ #ifndef mozilla_Services_h #define mozilla_Services_h #include "nscore.h" #include "nsCOMPtr.h" """ ) for name, iface, contractid in services: # Write out a forward declaration for the type in question segs = iface.split("::") for namespace in segs[:-1]: output.write("namespace %s {\n" % namespace) output.write("class %s;\n" % segs[-1]) for namespace in reversed(segs[:-1]): output.write("} // namespace %s\n" % namespace) # Write out the C-style function signature, and the C++ wrapper output.write( """ #ifdef MOZILLA_INTERNAL_API namespace mozilla { namespace services { /** * Fetch a cached instance of the %(name)s. * This function will return nullptr during XPCOM shutdown. * Prefer using static components to this method. * WARNING: This method is _not_ threadsafe! */ already_AddRefed<%(type)s> Get%(name)s(); } // namespace services } // namespace mozilla #endif // defined(MOZILLA_INTERNAL_API) """ % { "name": name, "type": iface, } ) output.write("#endif // !defined(mozilla_Services_h)\n") def services_cpp(output): output.write( """\ /* THIS FILE IS GENERATED BY Services.py - DO NOT EDIT */ """ ) output.write(CPP_INCLUDES) for name, iface, contractid in services: output.write( """ static %(type)s* g%(name)s = nullptr; namespace mozilla { namespace services { already_AddRefed<%(type)s> Get%(name)s() { if (MOZ_UNLIKELY(gXPCOMShuttingDown)) { return nullptr; } if (!g%(name)s) { nsCOMPtr<%(type)s> os = do_GetService("%(contractid)s"); os.swap(g%(name)s); } return do_AddRef(g%(name)s); } } } """ % { "name": name, "type": iface, "contractid": contractid, } ) output.write( """ /** * Clears service cache, sets gXPCOMShuttingDown */ void mozilla::services::Shutdown() { gXPCOMShuttingDown = true; """ ) for name, iface, contractid in services: output.write(" NS_IF_RELEASE(g%s);\n" % name) output.write("}\n")