Bug 729204 - Make docshell privacy notifications work across multiple processes. r=bz

This commit is contained in:
Josh Matthews 2012-04-19 20:13:20 -04:00
parent 1a589b3eab
commit 7e78dba969
15 changed files with 139 additions and 5 deletions

View File

@ -114,6 +114,8 @@ CPPSRCS = \
# static lib.
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += \

View File

@ -68,7 +68,8 @@ nsDSURIContentListener::nsDSURIContentListener(nsDocShell* aDocShell)
if (NS_UNLIKELY(!initializedPrefCache)) {
// Lock the pref so that the user's changes to it, if any, are ignored.
nsIPrefBranch *root = Preferences::GetRootBranch();
root->LockPref("b2g.ignoreXFrameOptions");
if (XRE_GetProcessType() != GeckoProcessType_Content)
root->LockPref("b2g.ignoreXFrameOptions");
Preferences::AddBoolVarCache(&sIgnoreXFrameOptions, "b2g.ignoreXFrameOptions");
initializedPrefCache = true;

View File

@ -41,6 +41,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/dom/ContentChild.h"
#include "mozilla/Util.h"
#ifdef MOZ_LOGGING
@ -714,6 +715,19 @@ ConvertLoadTypeToNavigationType(PRUint32 aLoadType)
static nsISHEntry* GetRootSHEntry(nsISHEntry *entry);
static void
IncreasePrivateDocShellCount()
{
gNumberOfPrivateDocShells++;
if (gNumberOfPrivateDocShells > 1 ||
XRE_GetProcessType() != GeckoProcessType_Content) {
return;
}
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
cc->SendPrivateDocShellsExist(true);
}
static void
DecreasePrivateDocShellCount()
{
@ -721,9 +735,16 @@ DecreasePrivateDocShellCount()
gNumberOfPrivateDocShells--;
if (!gNumberOfPrivateDocShells)
{
if (XRE_GetProcessType() == GeckoProcessType_Content) {
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
cc->SendPrivateDocShellsExist(false);
return;
}
nsCOMPtr<nsIObserverService> obsvc = mozilla::services::GetObserverService();
if (obsvc)
if (obsvc) {
obsvc->NotifyObservers(nsnull, "last-pb-context-exited", nsnull);
}
}
}
@ -2023,7 +2044,7 @@ nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing)
if (aUsePrivateBrowsing != mInPrivateBrowsing) {
mInPrivateBrowsing = aUsePrivateBrowsing;
if (aUsePrivateBrowsing) {
gNumberOfPrivateDocShells++;
IncreasePrivateDocShellCount();
} else {
DecreasePrivateDocShellCount();
}

View File

@ -47,10 +47,14 @@ DIRS += chrome \
navigation \
$(NULL)
XPCSHELL_TESTS = unit
include $(DEPTH)/config/autoconf.mk
XPCSHELL_TESTS = unit
# FIXME/bug 575918: out-of-process xpcshell is broken on OS X
ifneq ($(OS_ARCH),Darwin)
XPCSHELL_TESTS += unit_ipc
endif
ifneq (mobile,$(MOZ_BUILD_APP))
DIRS += browser
endif

View File

@ -0,0 +1,23 @@
if (typeof Cc === "undefined")
Cc = Components.classes;
if (typeof Ci === "undefined")
Ci = Components.interfaces;
function destroy_transient_docshell() {
var docshell = Cc["@mozilla.org/docshell;1"].createInstance(Ci.nsIDocShell);
docshell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing = true;
do_test_pending();
do_timeout(0, Components.utils.forceGC);
}
function run_test() {
var obs = {
observe: function(aSubject, aTopic, aData) {
do_check_eq(aTopic, "last-pb-context-exited");
do_test_finished();
}
};
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
os.addObserver(obs, "last-pb-context-exited", false);
destroy_transient_docshell();
}

View File

@ -5,3 +5,4 @@ tail =
[test_bug414201_jfif.js]
[test_bug442584.js]
[test_nsIDownloadHistory.js]
[test_pb_notification.js]

View File

@ -0,0 +1,20 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
function run_test() {
var notifications = 0;
var obs = {
observe: function(aSubject, aTopic, aData) {
do_check_eq(aTopic, "last-pb-context-exited");
notifications++;
}
};
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
os.addObserver(obs, "last-pb-context-exited", false);
run_test_in_child("../unit/test_pb_notification.js",
function() {
do_check_eq(notifications, 1);
do_test_finished();
});
}

View File

@ -0,0 +1,5 @@
[DEFAULT]
head =
tail =
[test_pb_notification_ipc.js]

View File

@ -820,5 +820,13 @@ ContentChild::RecvSetID(const PRUint64 &id)
return true;
}
bool
ContentChild::RecvLastPrivateDocShellDestroyed()
{
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
obs->NotifyObservers(nsnull, "last-pb-context-exited", nsnull);
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -170,6 +170,8 @@ public:
virtual bool RecvAppInfo(const nsCString& version, const nsCString& buildID);
virtual bool RecvSetID(const PRUint64 &id);
virtual bool RecvLastPrivateDocShellDestroyed();
#ifdef ANDROID
gfxIntSize GetScreenSize() { return mScreenSize; }
#endif

View File

@ -163,6 +163,7 @@ MemoryReportRequestParent::~MemoryReportRequestParent()
}
nsTArray<ContentParent*>* ContentParent::gContentParents;
nsTArray<ContentParent*>* ContentParent::gPrivateContent;
// The first content child has ID 1, so the chrome process can have ID 0.
static PRUint64 gContentChildID = 1;
@ -211,6 +212,7 @@ ContentParent::Init()
obs->AddObserver(this, "memory-pressure", false);
obs->AddObserver(this, "child-gc-request", false);
obs->AddObserver(this, "child-cc-request", false);
obs->AddObserver(this, "last-pb-context-exited", false);
#ifdef ACCESSIBILITY
obs->AddObserver(this, "a11y-init-or-shutdown", false);
#endif
@ -308,6 +310,7 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
obs->RemoveObserver(static_cast<nsIObserver*>(this), NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC);
obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-gc-request");
obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-cc-request");
obs->RemoveObserver(static_cast<nsIObserver*>(this), "last-pb-context-exited");
#ifdef ACCESSIBILITY
obs->RemoveObserver(static_cast<nsIObserver*>(this), "a11y-init-or-shutdown");
#endif
@ -339,6 +342,14 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
}
}
if (gPrivateContent) {
gPrivateContent->RemoveElement(this);
if (!gPrivateContent->Length()) {
delete gPrivateContent;
gPrivateContent = NULL;
}
}
mIsAlive = false;
if (obs) {
@ -723,6 +734,9 @@ ContentParent::Observe(nsISupports* aSubject,
else if (!strcmp(aTopic, "child-cc-request")){
SendCycleCollect();
}
else if (!strcmp(aTopic, "last-pb-context-exited")) {
unused << SendLastPrivateDocShellDestroyed();
}
#ifdef ACCESSIBILITY
// Make sure accessibility is running in content process when accessibility
// gets initiated in chrome process.
@ -1234,5 +1248,24 @@ ContentParent::RecvScriptError(const nsString& aMessage,
return true;
}
bool
ContentParent::RecvPrivateDocShellsExist(const bool& aExist)
{
if (!gPrivateContent)
gPrivateContent = new nsTArray<ContentParent*>;
if (aExist) {
gPrivateContent->AppendElement(this);
} else {
gPrivateContent->RemoveElement(this);
if (!gPrivateContent->Length()) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
obs->NotifyObservers(nsnull, "last-pb-context-exited", nsnull);
delete gPrivateContent;
gPrivateContent = NULL;
}
}
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -110,6 +110,7 @@ protected:
private:
static nsTArray<ContentParent*>* gContentParents;
static nsTArray<ContentParent*>* gPrivateContent;
// Hide the raw constructor methods since we don't want client code
// using them.
@ -222,6 +223,8 @@ private:
const PRUint32& aFlags,
const nsCString& aCategory);
virtual bool RecvPrivateDocShellsExist(const bool& aExist);
GeckoChildProcessHost* mSubprocess;
PRInt32 mGeolocationWatchID;

View File

@ -149,6 +149,9 @@ child:
SetID(PRUint64 id);
// Notify child that last-pb-context-exited notification was observed
LastPrivateDocShellDestroyed();
parent:
PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
@ -226,6 +229,9 @@ parent:
sync GetShowPasswordSetting()
returns (bool showPassword);
// Notify the parent of the presence or absence of private docshells
PrivateDocShellsExist(bool aExist);
both:
AsyncMessage(nsString aMessage, nsString aJSON);

View File

@ -53,6 +53,10 @@ extern JSBool
js_Stringify(JSContext *cx, js::Value *vp, JSObject *replacer, js::Value space,
js::StringBuffer &sb);
// Avoid build errors on certain platforms that define these names as constants
#undef STRICT
#undef LEGACY
/*
* The type of JSON decoding to perform. Strict decoding is to-the-spec;
* legacy decoding accepts a few non-JSON syntaxes historically accepted by the

View File

@ -13,6 +13,7 @@
[include:dom/indexedDB/test/unit/xpcshell.ini]
[include:content/xtf/test/unit/xpcshell.ini]
[include:docshell/test/unit/xpcshell.ini]
[include:docshell/test/unit_ipc/xpcshell.ini]
[include:embedding/tests/unit/xpcshell.ini]
[include:toolkit/components/commandlines/test/unit/xpcshell.ini]
[include:toolkit/components/contentprefs/tests/unit/xpcshell.ini]