diff options
Diffstat (limited to '')
-rw-r--r-- | xpcom/build/Services.py | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/xpcom/build/Services.py b/xpcom/build/Services.py new file mode 100644 index 0000000000..4c6c14807f --- /dev/null +++ b/xpcom/build/Services.py @@ -0,0 +1,170 @@ +# 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") |