1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set sw=4 ts=8 et tw=80 : */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla Content App.
18 * The Initial Developer of the Original Code is
19 * The Mozilla Foundation.
20 * Portions created by the Initial Developer are Copyright (C) 2009
21 * the Initial Developer. All Rights Reserved.
24 * Frederic Plourde <frederic.plourde@collabora.co.uk>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "ContentProcessParent.h"
42 #include "TabParent.h"
43 #include "mozilla/ipc/TestShellParent.h"
44 #include "mozilla/net/NeckoParent.h"
45 #include "nsIPrefBranch.h"
46 #include "nsIPrefBranch2.h"
47 #include "nsIPrefLocalizedString.h"
48 #include "nsIObserverService.h"
50 #include "nsAutoPtr.h"
52 #include "nsServiceManagerUtils.h"
53 #include "nsThreadUtils.h"
54 #include "nsChromeRegistryChrome.h"
56 using namespace mozilla::ipc
;
57 using namespace mozilla::net
;
58 using mozilla::MonitorAutoEnter
;
63 #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
65 ContentProcessParent
* ContentProcessParent::gSingleton
;
68 ContentProcessParent::GetSingleton(PRBool aForceNew
)
70 if (gSingleton
&& !gSingleton
->IsAlive())
73 if (!gSingleton
&& aForceNew
) {
74 nsRefPtr
<ContentProcessParent
> parent
= new ContentProcessParent();
76 nsCOMPtr
<nsIObserverService
> obs
=
77 do_GetService("@mozilla.org/observer-service;1");
79 if (NS_SUCCEEDED(obs
->AddObserver(parent
, "xpcom-shutdown",
82 nsCOMPtr
<nsIPrefBranch2
> prefs
83 (do_GetService(NS_PREFSERVICE_CONTRACTID
));
85 prefs
->AddObserver("", parent
, PR_FALSE
);
89 parent
, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC
, PR_FALSE
);
91 nsCOMPtr
<nsIThreadInternal
>
92 threadInt(do_QueryInterface(NS_GetCurrentThread()));
94 threadInt
->GetObserver(getter_AddRefs(parent
->mOldObserver
));
95 threadInt
->SetObserver(parent
);
103 ContentProcessParent::ActorDestroy(ActorDestroyReason why
)
105 nsCOMPtr
<nsIThreadObserver
>
106 kungFuDeathGrip(static_cast<nsIThreadObserver
*>(this));
107 nsCOMPtr
<nsIObserverService
>
108 obs(do_GetService("@mozilla.org/observer-service;1"));
110 obs
->RemoveObserver(static_cast<nsIObserver
*>(this), "xpcom-shutdown");
111 nsCOMPtr
<nsIThreadInternal
>
112 threadInt(do_QueryInterface(NS_GetCurrentThread()));
114 threadInt
->SetObserver(mOldObserver
);
115 if (mRunToCompletionDepth
)
116 mRunToCompletionDepth
= 0;
122 ContentProcessParent::CreateTab()
124 return static_cast<TabParent
*>(SendPIFrameEmbeddingConstructor());
128 ContentProcessParent::CreateTestShell()
130 return static_cast<TestShellParent
*>(SendPTestShellConstructor());
134 ContentProcessParent::DestroyTestShell(TestShellParent
* aTestShell
)
136 return PTestShellParent::Send__delete__(aTestShell
);
139 ContentProcessParent::ContentProcessParent()
140 : mMonitor("ContentProcessParent::mMonitor")
141 , mRunToCompletionDepth(0)
142 , mShouldCallUnblockChild(false)
145 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
146 mSubprocess
= new GeckoChildProcessHost(GeckoProcessType_Content
);
147 mSubprocess
->AsyncLaunch();
148 Open(mSubprocess
->GetChannel(), mSubprocess
->GetChildProcessHandle());
150 nsCOMPtr
<nsIChromeRegistry
> registrySvc
= nsChromeRegistry::GetService();
151 nsChromeRegistryChrome
* chromeRegistry
=
152 static_cast<nsChromeRegistryChrome
*>(registrySvc
.get());
153 chromeRegistry
->SendRegisteredChrome(this);
156 ContentProcessParent::~ContentProcessParent()
158 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
159 //If the previous content process has died, a new one could have
160 //been started since.
161 if (gSingleton
== this)
166 ContentProcessParent::IsAlive()
172 ContentProcessParent::RecvGetPrefType(const nsCString
& prefName
,
173 PRInt32
* retValue
, nsresult
* rv
)
178 *rv
= mPrefService
->GetPrefType(prefName
.get(), retValue
);
183 ContentProcessParent::RecvGetBoolPref(const nsCString
& prefName
,
184 PRBool
* retValue
, nsresult
* rv
)
186 *retValue
= PR_FALSE
;
189 *rv
= mPrefService
->GetBoolPref(prefName
.get(), retValue
);
194 ContentProcessParent::RecvGetIntPref(const nsCString
& prefName
,
195 PRInt32
* retValue
, nsresult
* rv
)
200 *rv
= mPrefService
->GetIntPref(prefName
.get(), retValue
);
205 ContentProcessParent::RecvGetCharPref(const nsCString
& prefName
,
206 nsCString
* retValue
, nsresult
* rv
)
209 *rv
= mPrefService
->GetCharPref(prefName
.get(), getter_Copies(*retValue
));
214 ContentProcessParent::RecvGetPrefLocalizedString(const nsCString
& prefName
,
215 nsString
* retValue
, nsresult
* rv
)
218 nsCOMPtr
<nsIPrefLocalizedString
> string
;
219 *rv
= mPrefService
->GetComplexValue(prefName
.get(),
220 NS_GET_IID(nsIPrefLocalizedString
), getter_AddRefs(string
));
222 if (NS_SUCCEEDED(*rv
))
223 string
->GetData(getter_Copies(*retValue
));
229 ContentProcessParent::RecvPrefHasUserValue(const nsCString
& prefName
,
230 PRBool
* retValue
, nsresult
* rv
)
232 *retValue
= PR_FALSE
;
235 *rv
= mPrefService
->PrefHasUserValue(prefName
.get(), retValue
);
240 ContentProcessParent::RecvPrefIsLocked(const nsCString
& prefName
,
241 PRBool
* retValue
, nsresult
* rv
)
243 *retValue
= PR_FALSE
;
246 *rv
= mPrefService
->PrefIsLocked(prefName
.get(), retValue
);
252 ContentProcessParent::RecvGetChildList(const nsCString
& domain
,
253 nsTArray
<nsCString
>* list
, nsresult
* rv
)
259 *rv
= mPrefService
->GetChildList(domain
.get(), &count
, &childArray
);
261 if (NS_SUCCEEDED(*rv
)) {
262 list
->SetCapacity(count
);
263 for (PRUint32 i
= 0; i
< count
; ++i
)
264 *(list
->AppendElement()) = childArray
[i
];
271 ContentProcessParent::EnsurePrefService()
275 mPrefService
= do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
);
276 NS_ASSERTION(NS_SUCCEEDED(rv
),
277 "We lost prefService in the Chrome process !");
281 NS_IMPL_THREADSAFE_ISUPPORTS2(ContentProcessParent
,
287 DeleteSubprocess(GeckoChildProcessHost
* aSubprocess
)
294 ContentProcessParent::Observe(nsISupports
* aSubject
,
296 const PRUnichar
* aData
)
298 if (!strcmp(aTopic
, "xpcom-shutdown") && mSubprocess
) {
299 // remove the global remote preferences observers
300 nsCOMPtr
<nsIPrefBranch2
> prefs
301 (do_GetService(NS_PREFSERVICE_CONTRACTID
));
304 prefs
->RemoveObserver("", this);
309 XRE_GetIOMessageLoop()->PostTask(
311 NewRunnableFunction(DeleteSubprocess
, mSubprocess
));
312 mSubprocess
= nsnull
;
315 // listening for remotePrefs...
316 if (!strcmp(aTopic
, "nsPref:changed")) {
317 // We know prefs are ASCII here.
318 NS_LossyConvertUTF16toASCII
strData(aData
);
320 SendNotifyRemotePrefObserver(strData
);
323 if (!strcmp(aTopic
, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC
) && mSubprocess
) {
324 NS_ConvertUTF16toUTF8
dataStr(aData
);
325 const char *offline
= dataStr
.get();
327 SendSetOffline(!strcmp(offline
, "true") ? true : false);
332 PIFrameEmbeddingParent
*
333 ContentProcessParent::AllocPIFrameEmbedding()
335 TabParent
* parent
= new TabParent();
343 ContentProcessParent::DeallocPIFrameEmbedding(PIFrameEmbeddingParent
* frame
)
345 TabParent
* parent
= static_cast<TabParent
*>(frame
);
351 ContentProcessParent::AllocPTestShell()
353 return new TestShellParent();
357 ContentProcessParent::DeallocPTestShell(PTestShellParent
* shell
)
364 ContentProcessParent::AllocPNecko()
366 return new NeckoParent();
370 ContentProcessParent::DeallocPNecko(PNeckoParent
* necko
)
377 ContentProcessParent::ReportChildAlreadyBlocked()
379 if (!mRunToCompletionDepth
) {
381 printf("Running to completion...\n");
383 mRunToCompletionDepth
= 1;
384 mShouldCallUnblockChild
= false;
389 ContentProcessParent::RequestRunToCompletion()
391 if (!mRunToCompletionDepth
&&
394 printf("Running to completion...\n");
396 mRunToCompletionDepth
= 1;
397 mShouldCallUnblockChild
= true;
399 return !!mRunToCompletionDepth
;
402 /* void onDispatchedEvent (in nsIThreadInternal thread); */
404 ContentProcessParent::OnDispatchedEvent(nsIThreadInternal
*thread
)
407 return mOldObserver
->OnDispatchedEvent(thread
);
412 /* void onProcessNextEvent (in nsIThreadInternal thread, in boolean mayWait, in unsigned long recursionDepth); */
414 ContentProcessParent::OnProcessNextEvent(nsIThreadInternal
*thread
,
416 PRUint32 recursionDepth
)
418 if (mRunToCompletionDepth
)
419 ++mRunToCompletionDepth
;
422 return mOldObserver
->OnProcessNextEvent(thread
, mayWait
, recursionDepth
);
427 /* void afterProcessNextEvent (in nsIThreadInternal thread, in unsigned long recursionDepth); */
429 ContentProcessParent::AfterProcessNextEvent(nsIThreadInternal
*thread
,
430 PRUint32 recursionDepth
)
432 if (mRunToCompletionDepth
&&
433 !--mRunToCompletionDepth
) {
435 printf("... ran to completion.\n");
437 if (mShouldCallUnblockChild
) {
438 mShouldCallUnblockChild
= false;
444 return mOldObserver
->AfterProcessNextEvent(thread
, recursionDepth
);
450 } // namespace mozilla