1 : /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Mozilla Corporation
19 : * Portions created by the Initial Developer are Copyright (C) 2010
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 : #ifndef nsFrameMessageManager_h__
38 : #define nsFrameMessageManager_h__
39 :
40 : #include "nsIFrameMessageManager.h"
41 : #include "nsIObserver.h"
42 : #include "nsCOMPtr.h"
43 : #include "nsAutoPtr.h"
44 : #include "nsCOMArray.h"
45 : #include "nsTArray.h"
46 : #include "nsIAtom.h"
47 : #include "nsCycleCollectionParticipant.h"
48 : #include "nsTArray.h"
49 : #include "nsIPrincipal.h"
50 : #include "nsIXPConnect.h"
51 : #include "nsDataHashtable.h"
52 : #include "mozilla/Services.h"
53 : #include "nsIObserverService.h"
54 : #include "nsThreadUtils.h"
55 :
56 : namespace mozilla {
57 : namespace dom {
58 : class ContentParent;
59 : }
60 : }
61 :
62 : class nsAXPCNativeCallContext;
63 : struct JSContext;
64 : struct JSObject;
65 :
66 : struct nsMessageListenerInfo
67 994 : {
68 : nsCOMPtr<nsIFrameMessageListener> mListener;
69 : nsCOMPtr<nsIAtom> mMessage;
70 : };
71 :
72 : typedef bool (*nsLoadScriptCallback)(void* aCallbackData, const nsAString& aURL);
73 : typedef bool (*nsSyncMessageCallback)(void* aCallbackData,
74 : const nsAString& aMessage,
75 : const nsAString& aJSON,
76 : InfallibleTArray<nsString>* aJSONRetVal);
77 : typedef bool (*nsAsyncMessageCallback)(void* aCallbackData,
78 : const nsAString& aMessage,
79 : const nsAString& aJSON);
80 :
81 : class nsFrameMessageManager : public nsIContentFrameMessageManager,
82 : public nsIChromeFrameMessageManager
83 : {
84 : public:
85 250 : nsFrameMessageManager(bool aChrome,
86 : nsSyncMessageCallback aSyncCallback,
87 : nsAsyncMessageCallback aAsyncCallback,
88 : nsLoadScriptCallback aLoadScriptCallback,
89 : void* aCallbackData,
90 : nsFrameMessageManager* aParentManager,
91 : JSContext* aContext,
92 : bool aGlobal = false,
93 : bool aProcessManager = false)
94 : : mChrome(aChrome), mGlobal(aGlobal), mIsProcessManager(aProcessManager),
95 : mHandlingMessage(false), mDisconnected(false), mParentManager(aParentManager),
96 : mSyncCallback(aSyncCallback), mAsyncCallback(aAsyncCallback),
97 : mLoadScriptCallback(aLoadScriptCallback), mCallbackData(aCallbackData),
98 250 : mContext(aContext)
99 : {
100 250 : NS_ASSERTION(mContext || (aChrome && !aParentManager) || aProcessManager,
101 : "Should have mContext in non-global/non-process manager!");
102 250 : NS_ASSERTION(aChrome || !aParentManager, "Should not set parent manager!");
103 : // This is a bit hackish. When parent manager is global, we want
104 : // to attach the window message manager to it immediately.
105 : // Is it just the frame message manager which waits until the
106 : // content process is running.
107 250 : if (mParentManager && (mCallbackData || IsWindowLevel())) {
108 11 : mParentManager->AddChildManager(this);
109 : }
110 250 : }
111 :
112 250 : ~nsFrameMessageManager()
113 500 : {
114 261 : for (PRInt32 i = mChildManagers.Count(); i > 0; --i) {
115 11 : static_cast<nsFrameMessageManager*>(mChildManagers[i - 1])->
116 11 : Disconnect(false);
117 : }
118 250 : if (mIsProcessManager) {
119 22 : if (this == sParentProcessManager) {
120 11 : sParentProcessManager = nsnull;
121 : }
122 22 : if (this == sChildProcessManager) {
123 0 : sChildProcessManager = nsnull;
124 0 : delete sPendingSameProcessAsyncMessages;
125 0 : sPendingSameProcessAsyncMessages = nsnull;
126 : }
127 22 : if (this == sSameProcessParentManager) {
128 11 : sSameProcessParentManager = nsnull;
129 : }
130 : }
131 250 : }
132 :
133 66 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
134 8780 : NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameMessageManager,
135 : nsIContentFrameMessageManager)
136 : NS_DECL_NSIFRAMEMESSAGEMANAGER
137 : NS_DECL_NSISYNCMESSAGESENDER
138 : NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
139 : NS_DECL_NSICHROMEFRAMEMESSAGEMANAGER
140 : NS_DECL_NSITREEITEMFRAMEMESSAGEMANAGER
141 :
142 : static nsFrameMessageManager*
143 : NewProcessMessageManager(mozilla::dom::ContentParent* aProcess);
144 :
145 : nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
146 : bool aSync, const nsAString& aJSON,
147 : JSObject* aObjectsArray,
148 : InfallibleTArray<nsString>* aJSONRetVal,
149 : JSContext* aContext = nsnull);
150 : void AddChildManager(nsFrameMessageManager* aManager,
151 : bool aLoadScripts = true);
152 0 : void RemoveChildManager(nsFrameMessageManager* aManager)
153 : {
154 0 : mChildManagers.RemoveObject(aManager);
155 0 : }
156 :
157 : void Disconnect(bool aRemoveFromParent = true);
158 : void SetCallbackData(void* aData, bool aLoadScripts = true);
159 0 : void* GetCallbackData() { return mCallbackData; }
160 : void GetParamsForMessage(const jsval& aObject,
161 : JSContext* aCx,
162 : nsAString& aJSON);
163 : nsresult SendAsyncMessageInternal(const nsAString& aMessage,
164 : const nsAString& aJSON);
165 0 : JSContext* GetJSContext() { return mContext; }
166 0 : void SetJSContext(JSContext* aCx) { mContext = aCx; }
167 : void RemoveFromParent();
168 0 : nsFrameMessageManager* GetParentManager() { return mParentManager; }
169 0 : void SetParentManager(nsFrameMessageManager* aParent)
170 : {
171 0 : NS_ASSERTION(!mParentManager, "We have parent manager already!");
172 0 : NS_ASSERTION(mChrome, "Should not set parent manager!");
173 0 : mParentManager = aParent;
174 0 : }
175 228 : bool IsGlobal() { return mGlobal; }
176 0 : bool IsWindowLevel() { return mParentManager && mParentManager->IsGlobal(); }
177 :
178 : static nsFrameMessageManager* GetParentProcessManager()
179 : {
180 : return sParentProcessManager;
181 : }
182 : static nsFrameMessageManager* GetChildProcessManager()
183 : {
184 : return sChildProcessManager;
185 : }
186 : protected:
187 : friend class MMListenerRemover;
188 : nsTArray<nsMessageListenerInfo> mListeners;
189 : nsCOMArray<nsIContentFrameMessageManager> mChildManagers;
190 : bool mChrome;
191 : bool mGlobal;
192 : bool mIsProcessManager;
193 : bool mHandlingMessage;
194 : bool mDisconnected;
195 : nsFrameMessageManager* mParentManager;
196 : nsSyncMessageCallback mSyncCallback;
197 : nsAsyncMessageCallback mAsyncCallback;
198 : nsLoadScriptCallback mLoadScriptCallback;
199 : void* mCallbackData;
200 : JSContext* mContext;
201 : nsTArray<nsString> mPendingScripts;
202 : public:
203 : static nsFrameMessageManager* sParentProcessManager;
204 : static nsFrameMessageManager* sChildProcessManager;
205 : static nsFrameMessageManager* sSameProcessParentManager;
206 : static nsTArray<nsCOMPtr<nsIRunnable> >* sPendingSameProcessAsyncMessages;
207 : };
208 :
209 : void
210 : ContentScriptErrorReporter(JSContext* aCx,
211 : const char* aMessage,
212 : JSErrorReport* aReport);
213 :
214 : class nsScriptCacheCleaner;
215 :
216 : struct nsFrameJSScriptExecutorHolder
217 : {
218 0 : nsFrameJSScriptExecutorHolder(JSScript* aScript) : mScript(aScript)
219 0 : { MOZ_COUNT_CTOR(nsFrameJSScriptExecutorHolder); }
220 0 : ~nsFrameJSScriptExecutorHolder()
221 0 : { MOZ_COUNT_DTOR(nsFrameJSScriptExecutorHolder); }
222 : JSScript* mScript;
223 : };
224 :
225 : class nsFrameScriptExecutor
226 : {
227 : public:
228 : static void Shutdown();
229 : protected:
230 : friend class nsFrameScriptCx;
231 0 : nsFrameScriptExecutor() : mCx(nsnull), mCxStackRefCnt(0),
232 0 : mDelayedCxDestroy(false)
233 0 : { MOZ_COUNT_CTOR(nsFrameScriptExecutor); }
234 0 : ~nsFrameScriptExecutor()
235 0 : { MOZ_COUNT_DTOR(nsFrameScriptExecutor); }
236 : void DidCreateCx();
237 : // Call this when you want to destroy mCx.
238 : void DestroyCx();
239 : void LoadFrameScriptInternal(const nsAString& aURL);
240 : bool InitTabChildGlobalInternal(nsISupports* aScope);
241 : static void Traverse(nsFrameScriptExecutor *tmp,
242 : nsCycleCollectionTraversalCallback &cb);
243 : nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
244 : JSContext* mCx;
245 : PRUint32 mCxStackRefCnt;
246 : bool mDelayedCxDestroy;
247 : nsCOMPtr<nsIPrincipal> mPrincipal;
248 : static nsDataHashtable<nsStringHashKey, nsFrameJSScriptExecutorHolder*>* sCachedScripts;
249 : static nsRefPtr<nsScriptCacheCleaner> sScriptCacheCleaner;
250 : };
251 :
252 : class nsFrameScriptCx
253 : {
254 : public:
255 0 : nsFrameScriptCx(nsISupports* aOwner, nsFrameScriptExecutor* aExec)
256 0 : : mOwner(aOwner), mExec(aExec)
257 : {
258 0 : ++(mExec->mCxStackRefCnt);
259 0 : }
260 0 : ~nsFrameScriptCx()
261 0 : {
262 0 : if (--(mExec->mCxStackRefCnt) == 0 &&
263 : mExec->mDelayedCxDestroy) {
264 0 : mExec->DestroyCx();
265 : }
266 0 : }
267 : nsCOMPtr<nsISupports> mOwner;
268 : nsFrameScriptExecutor* mExec;
269 : };
270 :
271 : class nsScriptCacheCleaner : public nsIObserver
272 : {
273 : NS_DECL_ISUPPORTS
274 :
275 0 : nsScriptCacheCleaner()
276 0 : {
277 0 : nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
278 0 : if (obsSvc)
279 0 : obsSvc->AddObserver(this, "xpcom-shutdown", false);
280 0 : }
281 :
282 0 : NS_IMETHODIMP Observe(nsISupports *aSubject,
283 : const char *aTopic,
284 : const PRUnichar *aData)
285 : {
286 0 : nsFrameScriptExecutor::Shutdown();
287 0 : return NS_OK;
288 : }
289 : };
290 :
291 : #endif
|