summaryrefslogtreecommitdiffstats
path: root/xpcom/components/StaticComponents.cpp.in
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xpcom/components/StaticComponents.cpp.in410
1 files changed, 410 insertions, 0 deletions
diff --git a/xpcom/components/StaticComponents.cpp.in b/xpcom/components/StaticComponents.cpp.in
new file mode 100644
index 0000000000..7f3fee6859
--- /dev/null
+++ b/xpcom/components/StaticComponents.cpp.in
@@ -0,0 +1,410 @@
+/* -*- 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/. */
+
+#include "StaticComponents.h"
+
+#include "mozilla/ArrayUtils.h"
+#ifdef MOZ_BACKGROUNDTASKS
+# include "mozilla/BackgroundTasks.h"
+#endif
+#include "mozilla/PerfectHash.h"
+#include "mozilla/ResultExtensions.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "mozJSModuleLoader.h"
+#include "nsCOMPtr.h"
+#include "nsComponentManager.h"
+#include "nsContentUtils.h"
+#include "nsIFactory.h"
+#include "nsISupports.h"
+#include "nsIXPConnect.h"
+#include "nsString.h"
+#include "nsStringEnumerator.h"
+#include "nsTArray.h"
+#include "xptdata.h"
+#include "xptinfo.h"
+#include "js/PropertyAndElement.h" // JS_GetProperty
+
+// Cleanup pollution from zipstruct.h
+#undef UNSUPPORTED
+
+// Public includes
+//# @includes@
+
+// Relative includes
+//# @relative_includes@
+
+//# @decls@
+
+namespace mozilla {
+
+using dom::AutoJSAPI;
+
+namespace xpcom {
+
+static constexpr uint32_t kNoContractID = 0xffffffff;
+
+namespace {
+// Template helpers for constructor function sanity checks.
+template <typename T>
+struct RemoveAlreadyAddRefed {
+ using Type = T;
+};
+
+template <typename T>
+struct RemoveAlreadyAddRefed<already_AddRefed<T>> {
+ using Type = T;
+};
+} // anonymous namespace
+
+
+uint8_t gInvalidContracts[kContractCount / 8 + 1];
+
+static StaticRefPtr<nsISupports> gServiceInstances[kStaticModuleCount];
+
+uint8_t gInitCalled[kModuleInitCount / 8 + 1];
+
+static const char gStrings[] =
+//# @strings@
+ "";
+
+const StaticCategory gStaticCategories[kStaticCategoryCount] = {
+//# @categories@
+};
+const StaticCategoryEntry gStaticCategoryEntries[] = {
+//# @category_entries@
+};
+
+const nsXPTInterface gInterfaces[] = {
+//# @interfaces@
+};
+
+const StringOffset gComponentJSMs[] = {
+//# @component_jsms@
+};
+
+const StringOffset gComponentESModules[] = {
+//# @component_esmodules@
+};
+
+/**
+ * Returns a nsCString corresponding to the given entry in the `gStrings` string
+ * table. The resulting nsCString points directly to static storage, and does
+ * not incur any memory allocation overhead.
+ */
+static inline nsCString GetString(const StringOffset& aOffset) {
+ const char* str = &gStrings[aOffset.mOffset];
+ nsCString result;
+ result.AssignLiteral(str, strlen(str));
+ return result;
+}
+
+nsCString ContractEntry::ContractID() const {
+ return GetString(mContractID);
+}
+
+bool ContractEntry::Matches(const nsACString& aContractID) const {
+ return aContractID == ContractID() && Module().Active();
+}
+
+enum class ComponentType { JSM, ESM };
+
+template <ComponentType type>
+static nsresult ConstructJSMOrESMComponent(const nsACString& aURI,
+ const char* aConstructor,
+ nsISupports** aResult) {
+ if (!nsComponentManagerImpl::JSLoaderReady()) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ AutoJSAPI jsapi;
+ MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope()));
+ JSContext* cx = jsapi.cx();
+
+ JS::Rooted<JSObject*> exports(cx);
+ if constexpr (type == ComponentType::JSM) {
+ JS::Rooted<JSObject*> global(cx);
+ MOZ_TRY(mozJSModuleLoader::Get()->Import(cx, aURI, &global, &exports));
+ } else {
+ MOZ_TRY(mozJSModuleLoader::Get()->ImportESModule(cx, aURI, &exports));
+ }
+
+ JS::Rooted<JS::Value> ctor(cx);
+ if (!JS_GetProperty(cx, exports, aConstructor, &ctor) ||
+ !ctor.isObject()) {
+ return NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED;
+ }
+
+ JS::Rooted<JSObject*> inst(cx);
+ if (!JS::Construct(cx, ctor, JS::HandleValueArray::empty(), &inst)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return nsContentUtils::XPConnect()->WrapJS(cx, inst, NS_GET_IID(nsISupports),
+ (void**)aResult);
+}
+
+static nsresult ConstructJSMComponent(const nsACString& aURI,
+ const char* aConstructor,
+ nsISupports** aResult) {
+ return ConstructJSMOrESMComponent<ComponentType::JSM>(
+ aURI, aConstructor, aResult);
+}
+
+static nsresult ConstructESModuleComponent(const nsACString& aURI,
+ const char* aConstructor,
+ nsISupports** aResult) {
+ return ConstructJSMOrESMComponent<ComponentType::ESM>(
+ aURI, aConstructor, aResult);
+}
+
+//# @module_cid_table@
+
+//# @module_contract_id_table@
+
+//# @js_services_table@
+
+//# @protocol_handlers_table@
+
+static inline bool CalledInit(size_t aIdx) {
+ return GetBit(gInitCalled, aIdx);
+}
+
+static nsresult CallInitFunc(size_t aIdx) {
+ if (CalledInit(aIdx)) {
+ return NS_OK;
+ }
+
+ nsresult rv = NS_OK;
+ switch (aIdx) {
+//# @init_funcs@
+ }
+
+ SetBit(gInitCalled, aIdx);
+
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ return rv;
+}
+
+static void CallUnloadFuncs() {
+//# @unload_funcs@
+}
+
+nsresult CreateInstanceImpl(ModuleID aID, const nsIID& aIID, void** aResult) {
+ // The full set of constructors for all static modules.
+ // This switch statement will be compiled to a relative address jump table
+ // with no runtime relocations and a single indirect jump.
+ switch (aID) {
+//# @constructors@
+ }
+
+ MOZ_ASSERT_UNREACHABLE("Constructor didn't return");
+ return NS_ERROR_FAILURE;
+}
+
+
+namespace {
+
+class StaticModuleFactory final : public nsIFactory {
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFACTORY
+
+ explicit StaticModuleFactory(ModuleID aID) : mID(aID) {}
+
+private:
+ ~StaticModuleFactory() = default;
+
+ const ModuleID mID;
+};
+
+NS_IMPL_ISUPPORTS(StaticModuleFactory, nsIFactory)
+
+NS_IMETHODIMP StaticModuleFactory::CreateInstance(const nsIID& aIID,
+ void** aResult) {
+ return CreateInstanceImpl(mID, aIID, aResult);
+}
+
+} // anonymous namespace
+
+
+already_AddRefed<nsIFactory> StaticModule::GetFactory() const {
+ return do_AddRef(new StaticModuleFactory(ID()));
+}
+
+bool StaticModule::Active() const {
+ return FastProcessSelectorMatches(mProcessSelector);
+}
+
+bool StaticModule::Overridable() const {
+ return mContractID.mOffset != kNoContractID;
+}
+
+nsCString StaticModule::ContractID() const {
+ MOZ_ASSERT(Overridable());
+ return GetString(mContractID);
+}
+
+nsresult StaticModule::CreateInstance(const nsIID& aIID, void** aResult) const {
+ return CreateInstanceImpl(ID(), aIID, aResult);
+}
+
+GetServiceHelper StaticModule::GetService() const {
+ return { ID(), nullptr };
+}
+
+GetServiceHelper StaticModule::GetService(nsresult* aRv) const {
+ return { ID(), aRv };
+}
+
+
+nsISupports* StaticModule::ServiceInstance() const {
+ return gServiceInstances[Idx()];
+}
+
+void StaticModule::SetServiceInstance(
+ already_AddRefed<nsISupports> aInst) const {
+ gServiceInstances[Idx()] = aInst;
+}
+
+
+nsCString StaticCategoryEntry::Entry() const {
+ return GetString(mEntry);
+}
+
+nsCString StaticCategoryEntry::Value() const {
+ return GetString(mValue);
+}
+
+bool StaticCategoryEntry::Active() const {
+ if (!FastProcessSelectorMatches(mProcessSelector)) {
+ return false;
+ }
+#ifdef MOZ_BACKGROUNDTASKS
+ if (MOZ_UNLIKELY(BackgroundTasks::IsBackgroundTaskMode())) {
+ return mBackgroundTasksSelector != Module::BackgroundTasksSelector::NO_TASKS;
+ }
+#endif /* MOZ_BACKGROUNDTASKS */
+ return true;
+}
+
+nsCString StaticCategory::Name() const {
+ return GetString(mName);
+}
+
+nsCString JSServiceEntry::Name() const {
+ return GetString(mName);
+}
+
+JSServiceEntry::InterfaceList JSServiceEntry::Interfaces() const {
+ InterfaceList iids;
+ iids.SetCapacity(mInterfaceCount);
+
+ for (size_t i = 0; i < mInterfaceCount; i++) {
+ nsXPTInterface ifaceID = gInterfaces[mInterfaceOffset.mOffset + i];
+ iids.AppendElement(&nsXPTInterfaceInfo::Get(ifaceID)->IID());
+ }
+ return iids;
+}
+
+
+/* static */
+const JSServiceEntry* JSServiceEntry::Lookup(const nsACString& aName) {
+ return LookupJSService(aName);
+}
+
+nsCString StaticProtocolHandler::Scheme() const {
+ return GetString(mScheme);
+}
+
+/* static */
+const StaticProtocolHandler* StaticProtocolHandler::Lookup(const nsACString& aScheme) {
+ return LookupProtocolHandler(aScheme);
+}
+
+/* static */ const StaticModule* StaticComponents::LookupByCID(
+ const nsID& aCID) {
+ return ModuleByCID(aCID);
+}
+
+/* static */ const StaticModule* StaticComponents::LookupByContractID(
+ const nsACString& aContractID) {
+ if (const ContractEntry* entry = LookupContractID(aContractID)) {
+ if (!entry->Invalid()) {
+ return &entry->Module();
+ }
+ }
+ return nullptr;
+}
+
+/* static */ bool StaticComponents::InvalidateContractID(
+ const nsACString& aContractID, bool aInvalid) {
+ if (const ContractEntry* entry = LookupContractID(aContractID)) {
+ entry->SetInvalid(aInvalid);
+ return true;
+ }
+ return false;
+}
+
+/* static */ already_AddRefed<nsIUTF8StringEnumerator>
+StaticComponents::GetComponentJSMs() {
+ auto jsms = MakeUnique<nsTArray<nsCString>>(MOZ_ARRAY_LENGTH(gComponentJSMs));
+
+ for (const auto& entry : gComponentJSMs) {
+ jsms->AppendElement(GetString(entry));
+ }
+
+ nsCOMPtr<nsIUTF8StringEnumerator> result;
+ MOZ_ALWAYS_SUCCEEDS(NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(result),
+ jsms.release()));
+ return result.forget();
+}
+
+/* static */ already_AddRefed<nsIUTF8StringEnumerator>
+StaticComponents::GetComponentESModules() {
+ auto esModules = MakeUnique<nsTArray<nsCString>>(MOZ_ARRAY_LENGTH(gComponentESModules));
+
+ for (const auto& entry : gComponentESModules) {
+ esModules->AppendElement(GetString(entry));
+ }
+
+ nsCOMPtr<nsIUTF8StringEnumerator> result;
+ MOZ_ALWAYS_SUCCEEDS(NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(result),
+ esModules.release()));
+ return result.forget();
+}
+
+/* static */ Span<const JSServiceEntry> StaticComponents::GetJSServices() {
+ return { gJSServices, ArrayLength(gJSServices) };
+}
+
+/* static */ void StaticComponents::Shutdown() {
+ CallUnloadFuncs();
+}
+
+/* static */ const nsID& Components::GetCID(ModuleID aID) {
+ return gStaticModules[size_t(aID)].CID();
+}
+
+nsresult GetServiceHelper::operator()(const nsIID& aIID, void** aResult) const {
+ nsresult rv =
+ nsComponentManagerImpl::gComponentManager->GetService(mId, aIID, aResult);
+ return SetResult(rv);
+}
+
+nsresult CreateInstanceHelper::operator()(const nsIID& aIID,
+ void** aResult) const {
+ const auto& entry = gStaticModules[size_t(mId)];
+ if (!entry.Active()) {
+ return SetResult(NS_ERROR_FACTORY_NOT_REGISTERED);
+ }
+
+ nsresult rv = entry.CreateInstance(aIID, aResult);
+ return SetResult(rv);
+}
+
+} // namespace xpcom
+} // namespace mozilla