summaryrefslogtreecommitdiffstats
path: root/xpcom/components/StaticComponents.h
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/components/StaticComponents.h')
-rw-r--r--xpcom/components/StaticComponents.h284
1 files changed, 284 insertions, 0 deletions
diff --git a/xpcom/components/StaticComponents.h b/xpcom/components/StaticComponents.h
new file mode 100644
index 0000000000..ac4095f2f3
--- /dev/null
+++ b/xpcom/components/StaticComponents.h
@@ -0,0 +1,284 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef StaticComponents_h
+#define StaticComponents_h
+
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/Module.h"
+#include "mozilla/Span.h"
+#include "nsID.h"
+#include "nsStringFwd.h"
+#include "nscore.h"
+
+#include "mozilla/Components.h"
+#include "StaticComponentData.h"
+
+class nsIFactory;
+class nsIUTF8StringEnumerator;
+class nsISupports;
+template <typename T, size_t N>
+class AutoTArray;
+
+namespace mozilla {
+namespace xpcom {
+
+struct ContractEntry;
+struct StaticModule;
+
+struct StaticCategoryEntry;
+struct StaticCategory;
+
+struct StaticProtocolHandler;
+
+extern const StaticModule gStaticModules[kStaticModuleCount];
+
+extern const ContractEntry gContractEntries[kContractCount];
+extern uint8_t gInvalidContracts[kContractCount / 8 + 1];
+
+extern const StaticCategory gStaticCategories[kStaticCategoryCount];
+extern const StaticCategoryEntry gStaticCategoryEntries[];
+
+extern const StaticProtocolHandler
+ gStaticProtocolHandlers[kStaticProtocolHandlerCount];
+
+template <size_t N>
+static inline bool GetBit(const uint8_t (&aBits)[N], size_t aBit) {
+ static constexpr size_t width = sizeof(aBits[0]) * 8;
+
+ size_t idx = aBit / width;
+ MOZ_ASSERT(idx < N);
+ return aBits[idx] & (1 << (aBit % width));
+}
+
+template <size_t N>
+static inline void SetBit(uint8_t (&aBits)[N], size_t aBit,
+ bool aValue = true) {
+ static constexpr size_t width = sizeof(aBits[0]) * 8;
+
+ size_t idx = aBit / width;
+ MOZ_ASSERT(idx < N);
+ if (aValue) {
+ aBits[idx] |= 1 << (aBit % width);
+ } else {
+ aBits[idx] &= ~(1 << (aBit % width));
+ }
+}
+
+/**
+ * Represents a string entry in the static string table. Can be converted to a
+ * nsCString using GetString() in StaticComponents.cpp.
+ *
+ * This is a struct rather than a pure offset primarily for the purposes of type
+ * safety, but also so that it can easily be extended to include a static length
+ * in the future, if efficiency concerns warrant it.
+ */
+struct StringOffset final {
+ uint32_t mOffset;
+};
+
+/**
+ * Represents an offset into the interfaces table.
+ */
+struct InterfaceOffset final {
+ uint16_t mOffset;
+};
+
+/**
+ * Represents a static component entry defined in a `Classes` list in an XPCOM
+ * manifest. Handles creating instances of and caching service instances for
+ * that class.
+ */
+struct StaticModule {
+ nsID mCID;
+ StringOffset mContractID;
+ Module::ProcessSelector mProcessSelector;
+
+ const nsID& CID() const { return mCID; }
+
+ ModuleID ID() const { return ModuleID(this - gStaticModules); }
+
+ /**
+ * Returns this entry's index in the gStaticModules array.
+ */
+ size_t Idx() const { return size_t(ID()); }
+
+ /**
+ * Returns true if this component's corresponding contract ID is expected to
+ * be overridden at runtime. If so, it should always be looked up by its
+ * ContractID() when retrieving its service instance.
+ */
+ bool Overridable() const;
+
+ /**
+ * If this entry is overridable, returns its associated contract ID string.
+ * The component should always be looked up by this contract ID when
+ * retrieving its service instance.
+ *
+ * Note: This may *only* be called if Overridable() returns true.
+ */
+ nsCString ContractID() const;
+
+ /**
+ * Returns true if this entry is active. Typically this will only return false
+ * if the entry's process selector does not match this process.
+ */
+ bool Active() const;
+
+ already_AddRefed<nsIFactory> GetFactory() const;
+
+ nsresult CreateInstance(const nsIID& aIID, void** aResult) const;
+
+ GetServiceHelper GetService() const;
+ GetServiceHelper GetService(nsresult*) const;
+
+ nsISupports* ServiceInstance() const;
+ void SetServiceInstance(already_AddRefed<nsISupports> aInst) const;
+};
+
+/**
+ * Represents a static mapping between a contract ID string and a StaticModule
+ * entry.
+ */
+struct ContractEntry final {
+ StringOffset mContractID;
+ ModuleID mModuleID;
+
+ size_t Idx() const { return this - gContractEntries; }
+
+ nsCString ContractID() const;
+
+ const StaticModule& Module() const {
+ return gStaticModules[size_t(mModuleID)];
+ }
+
+ /**
+ * Returns true if this entry's underlying module is active, and its contract
+ * ID matches the given contract ID string. This is used by the PerfectHash
+ * function to determine whether to return a result for this entry.
+ */
+ bool Matches(const nsACString& aContractID) const;
+
+ /**
+ * Returns true if this entry has been invalidated, and should be ignored.
+ *
+ * Contract IDs may be overwritten at runtime. When that happens for a static
+ * contract ID, we mark its entry invalid, and ignore it thereafter.
+ */
+ bool Invalid() const { return GetBit(gInvalidContracts, Idx()); }
+
+ /**
+ * Marks this entry invalid (or unsets the invalid bit if aInvalid is false),
+ * after which it will be ignored in contract ID lookup attempts. See
+ * `Invalid()` above.
+ */
+ void SetInvalid(bool aInvalid = true) const {
+ return SetBit(gInvalidContracts, Idx(), aInvalid);
+ }
+};
+
+/**
+ * Represents a declared category manager entry declared in an XPCOM manifest.
+ *
+ * The entire set of static category entries is read at startup and loaded into
+ * the category manager's dynamic hash tables, so there is memory and
+ * initialization overhead for each entry in these tables. This may be further
+ * optimized in the future to reduce some of that overhead.
+ */
+struct StaticCategoryEntry final {
+ StringOffset mEntry;
+ StringOffset mValue;
+ Module::BackgroundTasksSelector mBackgroundTasksSelector;
+ Module::ProcessSelector mProcessSelector;
+
+ nsCString Entry() const;
+ nsCString Value() const;
+ bool Active() const;
+};
+
+struct StaticCategory final {
+ StringOffset mName;
+ uint16_t mStart;
+ uint16_t mCount;
+
+ nsCString Name() const;
+
+ const StaticCategoryEntry* begin() const {
+ return &gStaticCategoryEntries[mStart];
+ }
+ const StaticCategoryEntry* end() const {
+ return &gStaticCategoryEntries[mStart + mCount];
+ }
+};
+
+struct JSServiceEntry final {
+ using InterfaceList = AutoTArray<const nsIID*, 4>;
+
+ static const JSServiceEntry* Lookup(const nsACString& aName);
+
+ StringOffset mName;
+ ModuleID mModuleID;
+
+ InterfaceOffset mInterfaceOffset;
+
+ uint8_t mInterfaceCount;
+
+ nsCString Name() const;
+
+ const StaticModule& Module() const {
+ return gStaticModules[size_t(mModuleID)];
+ }
+
+ InterfaceList Interfaces() const;
+};
+
+struct StaticProtocolHandler final {
+ static const StaticProtocolHandler* Lookup(const nsACString& aScheme);
+ static const StaticProtocolHandler& Default() {
+ return gStaticProtocolHandlers[kDefaultProtocolHandlerIndex];
+ }
+
+ StringOffset mScheme;
+ uint32_t mProtocolFlags;
+ int32_t mDefaultPort;
+ ModuleID mModuleID;
+ bool mHasDynamicFlags;
+
+ nsCString Scheme() const;
+
+ const StaticModule& Module() const {
+ return gStaticModules[size_t(mModuleID)];
+ }
+};
+
+class StaticComponents final {
+ public:
+ static const StaticModule* LookupByCID(const nsID& aCID);
+
+ static const StaticModule* LookupByContractID(const nsACString& aContractID);
+
+ /**
+ * Marks a static contract ID entry invalid (or unsets the invalid bit if
+ * aInvalid is false). See `CategoryEntry::Invalid()`.
+ */
+ static bool InvalidateContractID(const nsACString& aContractID,
+ bool aInvalid = true);
+
+ static already_AddRefed<nsIUTF8StringEnumerator> GetComponentJSMs();
+ static already_AddRefed<nsIUTF8StringEnumerator> GetComponentESModules();
+
+ static Span<const JSServiceEntry> GetJSServices();
+
+ /**
+ * Calls any module unload from manifests whose components have been loaded.
+ */
+ static void Shutdown();
+};
+
+} // namespace xpcom
+} // namespace mozilla
+
+#endif // defined StaticComponents_h