summaryrefslogtreecommitdiffstats
path: root/js/xpconnect/src/xpcObjectHelper.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/xpconnect/src/xpcObjectHelper.h')
-rw-r--r--js/xpconnect/src/xpcObjectHelper.h137
1 files changed, 137 insertions, 0 deletions
diff --git a/js/xpconnect/src/xpcObjectHelper.h b/js/xpconnect/src/xpcObjectHelper.h
new file mode 100644
index 000000000..10090a901
--- /dev/null
+++ b/js/xpconnect/src/xpcObjectHelper.h
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=99: */
+/* 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 xpcObjectHelper_h
+#define xpcObjectHelper_h
+
+// Including 'windows.h' will #define GetClassInfo to something else.
+#ifdef XP_WIN
+#ifdef GetClassInfo
+#undef GetClassInfo
+#endif
+#endif
+
+#include "mozilla/Attributes.h"
+#include <stdint.h>
+#include "nsCOMPtr.h"
+#include "nsIClassInfo.h"
+#include "nsISupports.h"
+#include "nsIXPCScriptable.h"
+#include "nsWrapperCache.h"
+
+class xpcObjectHelper
+{
+public:
+ explicit xpcObjectHelper(nsISupports* aObject, nsWrapperCache* aCache = nullptr)
+ : mCanonical(nullptr)
+ , mObject(aObject)
+ , mCache(aCache)
+ {
+ if (!mCache) {
+ if (aObject)
+ CallQueryInterface(aObject, &mCache);
+ else
+ mCache = nullptr;
+ }
+ }
+
+ nsISupports* Object()
+ {
+ return mObject;
+ }
+
+ nsISupports* GetCanonical()
+ {
+ if (!mCanonical) {
+ mCanonicalStrong = do_QueryInterface(mObject);
+ mCanonical = mCanonicalStrong;
+ }
+ return mCanonical;
+ }
+
+ already_AddRefed<nsISupports> forgetCanonical()
+ {
+ MOZ_ASSERT(mCanonical, "Huh, no canonical to forget?");
+
+ if (!mCanonicalStrong)
+ mCanonicalStrong = mCanonical;
+ mCanonical = nullptr;
+ return mCanonicalStrong.forget();
+ }
+
+ nsIClassInfo* GetClassInfo()
+ {
+ if (mXPCClassInfo)
+ return mXPCClassInfo;
+ if (!mClassInfo)
+ mClassInfo = do_QueryInterface(mObject);
+ return mClassInfo;
+ }
+ nsXPCClassInfo* GetXPCClassInfo()
+ {
+ if (!mXPCClassInfo) {
+ CallQueryInterface(mObject, getter_AddRefs(mXPCClassInfo));
+ }
+ return mXPCClassInfo;
+ }
+
+ already_AddRefed<nsXPCClassInfo> forgetXPCClassInfo()
+ {
+ GetXPCClassInfo();
+
+ return mXPCClassInfo.forget();
+ }
+
+ // We assert that we can reach an nsIXPCScriptable somehow.
+ uint32_t GetScriptableFlags()
+ {
+ // Try getting an nsXPCClassInfo - this handles DOM scriptable helpers.
+ nsCOMPtr<nsIXPCScriptable> sinfo = GetXPCClassInfo();
+
+ // If that didn't work, try just QI-ing. This handles BackstagePass.
+ if (!sinfo)
+ sinfo = do_QueryInterface(GetCanonical());
+
+ // We should have something by now.
+ MOZ_ASSERT(sinfo);
+
+ // Grab the flags.
+ return sinfo->GetScriptableFlags();
+ }
+
+ nsWrapperCache* GetWrapperCache()
+ {
+ return mCache;
+ }
+
+protected:
+ xpcObjectHelper(nsISupports* aObject, nsISupports* aCanonical,
+ nsWrapperCache* aCache)
+ : mCanonical(aCanonical)
+ , mObject(aObject)
+ , mCache(aCache)
+ {
+ if (!mCache && aObject)
+ CallQueryInterface(aObject, &mCache);
+ }
+
+ nsCOMPtr<nsISupports> mCanonicalStrong;
+ nsISupports* MOZ_UNSAFE_REF("xpcObjectHelper has been specifically optimized "
+ "to avoid unnecessary AddRefs and Releases. "
+ "(see bug 565742)") mCanonical;
+
+private:
+ xpcObjectHelper(xpcObjectHelper& aOther) = delete;
+
+ nsISupports* MOZ_UNSAFE_REF("xpcObjectHelper has been specifically optimized "
+ "to avoid unnecessary AddRefs and Releases. "
+ "(see bug 565742)") mObject;
+ nsWrapperCache* mCache;
+ nsCOMPtr<nsIClassInfo> mClassInfo;
+ RefPtr<nsXPCClassInfo> mXPCClassInfo;
+};
+
+#endif