Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set ts=8 sts=4 et sw=4 tw=99: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef xpcObjectHelper_h
8 : #define xpcObjectHelper_h
9 :
10 : // Including 'windows.h' will #define GetClassInfo to something else.
11 : #ifdef XP_WIN
12 : #ifdef GetClassInfo
13 : #undef GetClassInfo
14 : #endif
15 : #endif
16 :
17 : #include "mozilla/Attributes.h"
18 : #include <stdint.h>
19 : #include "nsCOMPtr.h"
20 : #include "nsIClassInfo.h"
21 : #include "nsISupports.h"
22 : #include "nsIXPCScriptable.h"
23 : #include "nsWrapperCache.h"
24 :
25 9571 : class xpcObjectHelper
26 : {
27 : public:
28 8862 : explicit xpcObjectHelper(nsISupports* aObject, nsWrapperCache* aCache = nullptr)
29 8862 : : mCanonical(nullptr)
30 : , mObject(aObject)
31 8862 : , mCache(aCache)
32 : {
33 8862 : if (!mCache) {
34 8862 : if (aObject)
35 8862 : CallQueryInterface(aObject, &mCache);
36 : else
37 0 : mCache = nullptr;
38 : }
39 8862 : }
40 :
41 25402 : nsISupports* Object()
42 : {
43 25402 : return mObject;
44 : }
45 :
46 8777 : nsISupports* GetCanonical()
47 : {
48 8777 : if (!mCanonical) {
49 8267 : mCanonicalStrong = do_QueryInterface(mObject);
50 8267 : mCanonical = mCanonicalStrong;
51 : }
52 8777 : return mCanonical;
53 : }
54 :
55 5711 : already_AddRefed<nsISupports> forgetCanonical()
56 : {
57 5711 : MOZ_ASSERT(mCanonical, "Huh, no canonical to forget?");
58 :
59 5711 : if (!mCanonicalStrong)
60 0 : mCanonicalStrong = mCanonical;
61 5711 : mCanonical = nullptr;
62 5711 : return mCanonicalStrong.forget();
63 : }
64 :
65 11422 : nsIClassInfo* GetClassInfo()
66 : {
67 11422 : if (mXPCClassInfo)
68 10 : return mXPCClassInfo;
69 11412 : if (!mClassInfo)
70 7039 : mClassInfo = do_QueryInterface(mObject);
71 11412 : return mClassInfo;
72 : }
73 520 : nsXPCClassInfo* GetXPCClassInfo()
74 : {
75 520 : if (!mXPCClassInfo) {
76 515 : CallQueryInterface(mObject, getter_AddRefs(mXPCClassInfo));
77 : }
78 520 : return mXPCClassInfo;
79 : }
80 :
81 : already_AddRefed<nsXPCClassInfo> forgetXPCClassInfo()
82 : {
83 : GetXPCClassInfo();
84 :
85 : return mXPCClassInfo.forget();
86 : }
87 :
88 : // We assert that we can reach an nsIXPCScriptable somehow.
89 520 : uint32_t GetScriptableFlags()
90 : {
91 : // Try getting an nsXPCClassInfo - this handles DOM scriptable helpers.
92 1040 : nsCOMPtr<nsIXPCScriptable> sinfo = GetXPCClassInfo();
93 :
94 : // If that didn't work, try just QI-ing. This handles BackstagePass.
95 520 : if (!sinfo)
96 510 : sinfo = do_QueryInterface(GetCanonical());
97 :
98 : // We should have something by now.
99 520 : MOZ_ASSERT(sinfo);
100 :
101 : // Grab the flags.
102 1040 : return sinfo->GetScriptableFlags();
103 : }
104 :
105 18042 : nsWrapperCache* GetWrapperCache()
106 : {
107 18042 : return mCache;
108 : }
109 :
110 : protected:
111 709 : xpcObjectHelper(nsISupports* aObject, nsISupports* aCanonical,
112 : nsWrapperCache* aCache)
113 709 : : mCanonical(aCanonical)
114 : , mObject(aObject)
115 709 : , mCache(aCache)
116 : {
117 709 : if (!mCache && aObject)
118 309 : CallQueryInterface(aObject, &mCache);
119 709 : }
120 :
121 : nsCOMPtr<nsISupports> mCanonicalStrong;
122 : nsISupports* MOZ_UNSAFE_REF("xpcObjectHelper has been specifically optimized "
123 : "to avoid unnecessary AddRefs and Releases. "
124 : "(see bug 565742)") mCanonical;
125 :
126 : private:
127 : xpcObjectHelper(xpcObjectHelper& aOther) = delete;
128 :
129 : nsISupports* MOZ_UNSAFE_REF("xpcObjectHelper has been specifically optimized "
130 : "to avoid unnecessary AddRefs and Releases. "
131 : "(see bug 565742)") mObject;
132 : nsWrapperCache* mCache;
133 : nsCOMPtr<nsIClassInfo> mClassInfo;
134 : RefPtr<nsXPCClassInfo> mXPCClassInfo;
135 : };
136 :
137 : #endif
|