diff options
Diffstat (limited to 'js/xpconnect/src/xpcObjectHelper.h')
-rw-r--r-- | js/xpconnect/src/xpcObjectHelper.h | 137 |
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 |