Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Bug 1126014 - DomainPolicy support for e10s. r=mrbkap
Browse files Browse the repository at this point in the history
  • Loading branch information
krizsa committed Mar 24, 2015
1 parent 98880a6 commit 9ae27c5
Show file tree
Hide file tree
Showing 15 changed files with 600 additions and 18 deletions.
118 changes: 112 additions & 6 deletions caps/DomainPolicy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,50 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "DomainPolicy.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/unused.h"
#include "nsIMessageManager.h"
#include "nsScriptSecurityManager.h"

namespace mozilla {

using namespace ipc;
using namespace dom;

NS_IMPL_ISUPPORTS(DomainPolicy, nsIDomainPolicy)

DomainPolicy::DomainPolicy() : mBlacklist(new DomainSet())
, mSuperBlacklist(new DomainSet())
, mWhitelist(new DomainSet())
, mSuperWhitelist(new DomainSet())
{}
static nsresult
BroadcastDomainSetChange(DomainSetType aSetType, DomainSetChangeType aChangeType,
nsIURI* aDomain = nullptr)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default,
"DomainPolicy should only be exposed to the chrome process.");

nsTArray<ContentParent*> parents;
ContentParent::GetAll(parents);
if (!parents.Length()) {
return NS_OK;
}

OptionalURIParams uri;
SerializeURI(aDomain, uri);

for (uint32_t i = 0; i < parents.Length(); i++) {
unused << parents[i]->SendDomainSetChanged(aSetType, aChangeType, uri);
}
return NS_OK;
}

DomainPolicy::DomainPolicy() : mBlacklist(new DomainSet(BLACKLIST))
, mSuperBlacklist(new DomainSet(SUPER_BLACKLIST))
, mWhitelist(new DomainSet(WHITELIST))
, mSuperWhitelist(new DomainSet(SUPER_WHITELIST))
{
if (XRE_GetProcessType() == GeckoProcessType_Default) {
BroadcastDomainSetChange(NO_TYPE, ACTIVATE_POLICY);
}
}

DomainPolicy::~DomainPolicy()
{
Expand Down Expand Up @@ -75,10 +108,47 @@ DomainPolicy::Deactivate()
mSuperWhitelist = nullptr;

// Inform the SSM.
nsScriptSecurityManager::GetScriptSecurityManager()->DeactivateDomainPolicy();
nsScriptSecurityManager* ssm = nsScriptSecurityManager::GetScriptSecurityManager();
if (ssm) {
ssm->DeactivateDomainPolicy();
}
if (XRE_GetProcessType() == GeckoProcessType_Default) {
BroadcastDomainSetChange(NO_TYPE, DEACTIVATE_POLICY);
}
return NS_OK;
}

void
DomainPolicy::CloneDomainPolicy(DomainPolicyClone* aClone)
{
aClone->active() = true;
static_cast<DomainSet*>(mBlacklist.get())->CloneSet(&aClone->blacklist());
static_cast<DomainSet*>(mSuperBlacklist.get())->CloneSet(&aClone->superBlacklist());
static_cast<DomainSet*>(mWhitelist.get())->CloneSet(&aClone->whitelist());
static_cast<DomainSet*>(mSuperWhitelist.get())->CloneSet(&aClone->superWhitelist());
}

static
void
CopyURIs(const InfallibleTArray<URIParams>& aDomains, nsIDomainSet* aSet)
{
for (uint32_t i = 0; i < aDomains.Length(); i++) {
nsCOMPtr<nsIURI> uri = DeserializeURI(aDomains[i]);
aSet->Add(uri);
}
}

void
DomainPolicy::ApplyClone(DomainPolicyClone* aClone)
{
nsCOMPtr<nsIDomainSet> list;

CopyURIs(aClone->blacklist(), mBlacklist);
CopyURIs(aClone->whitelist(), mWhitelist);
CopyURIs(aClone->superBlacklist(), mSuperBlacklist);
CopyURIs(aClone->superWhitelist(), mSuperWhitelist);
}

static already_AddRefed<nsIURI>
GetCanonicalClone(nsIURI* aURI)
{
Expand All @@ -100,6 +170,9 @@ DomainSet::Add(nsIURI* aDomain)
nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
mHashTable.PutEntry(clone);
if (XRE_GetProcessType() == GeckoProcessType_Default)
return BroadcastDomainSetChange(mType, ADD_DOMAIN, aDomain);

return NS_OK;
}

Expand All @@ -109,13 +182,19 @@ DomainSet::Remove(nsIURI* aDomain)
nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
mHashTable.RemoveEntry(clone);
if (XRE_GetProcessType() == GeckoProcessType_Default)
return BroadcastDomainSetChange(mType, REMOVE_DOMAIN, aDomain);

return NS_OK;
}

NS_IMETHODIMP
DomainSet::Clear()
{
mHashTable.Clear();
if (XRE_GetProcessType() == GeckoProcessType_Default)
return BroadcastDomainSetChange(mType, CLEAR_DOMAINS);

return NS_OK;
}

Expand Down Expand Up @@ -160,4 +239,31 @@ DomainSet::ContainsSuperDomain(nsIURI* aDomain, bool* aContains)

}

NS_IMETHODIMP
DomainSet::GetType(uint32_t* aType)
{
*aType = mType;
return NS_OK;
}

static
PLDHashOperator
DomainEnumerator(nsURIHashKey* aEntry, void* aUserArg)
{
InfallibleTArray<URIParams>* uris = static_cast<InfallibleTArray<URIParams>*>(aUserArg);
nsIURI* key = aEntry->GetKey();

URIParams uri;
SerializeURI(key, uri);

uris->AppendElement(uri);
return PL_DHASH_NEXT;
}

void
DomainSet::CloneSet(InfallibleTArray<URIParams>* aDomains)
{
mHashTable.EnumerateEntries(DomainEnumerator, aDomains);
}

} /* namespace mozilla */
31 changes: 30 additions & 1 deletion caps/DomainPolicy.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,30 @@

namespace mozilla {

namespace dom {
class nsIContentParent;
};

namespace ipc {
class URIParams;
};

enum DomainSetChangeType{
ACTIVATE_POLICY,
DEACTIVATE_POLICY,
ADD_DOMAIN,
REMOVE_DOMAIN,
CLEAR_DOMAINS
};

enum DomainSetType{
NO_TYPE,
BLACKLIST,
SUPER_BLACKLIST,
WHITELIST,
SUPER_WHITELIST
};

class DomainPolicy : public nsIDomainPolicy
{
public:
Expand All @@ -35,11 +59,16 @@ class DomainSet : public nsIDomainSet
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMAINSET

DomainSet() {}
explicit DomainSet(DomainSetType aType)
: mType(aType)
{}

void CloneSet(InfallibleTArray<mozilla::ipc::URIParams>* aDomains);

protected:
virtual ~DomainSet() {}
nsTHashtable<nsURIHashKey> mHashTable;
DomainSetType mType;
};

} /* namespace mozilla */
Expand Down
22 changes: 20 additions & 2 deletions caps/nsIDomainPolicy.idl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
interface nsIURI;
interface nsIDomainSet;

%{ C++
namespace mozilla {
namespace dom {
class DomainPolicyClone;
}
}
%}

[ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);

/*
* When a domain policy is instantiated by invoking activateDomainPolicy() on
* nsIScriptSecurityManager, these domain sets are consulted when each new
Expand All @@ -20,7 +30,7 @@ interface nsIDomainSet;
* When deactivate() is invoked, the domain sets are emptied, and the
* nsIDomainPolicy ceases to have any effect on the system.
*/
[scriptable, builtinclass, uuid(27b10f54-f34b-42b7-8594-4348d3ad7953)]
[scriptable, builtinclass, uuid(82b24a20-6701-4d40-a0f9-f5dc7321b555)]
interface nsIDomainPolicy : nsISupports
{
readonly attribute nsIDomainSet blacklist;
Expand All @@ -29,11 +39,19 @@ interface nsIDomainPolicy : nsISupports
readonly attribute nsIDomainSet superWhitelist;

void deactivate();

[noscript, notxpcom] void cloneDomainPolicy(in DomainPolicyClonePtr aClone);
[noscript, notxpcom] void applyClone(in DomainPolicyClonePtr aClone);
};

[scriptable, builtinclass, uuid(946a01ff-6525-4007-a2c2-447ebe1875d3)]
[scriptable, builtinclass, uuid(665c981b-0a0f-4229-ac06-a826e02d4f69)]
interface nsIDomainSet : nsISupports
{
/*
* The type of the set. See: DomainSetType
*/
[noscript] readonly attribute uint32_t type;

/*
* Add a domain to the set. No-op if it already exists.
*/
Expand Down
25 changes: 24 additions & 1 deletion caps/nsIScriptSecurityManager.idl
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ interface nsILoadContext;

%{ C++
#include "jspubtd.h"

namespace mozilla {
namespace dom {
class DomainPolicyClone;
}
}
%}

[ptr] native JSContextPtr(JSContext);
[ptr] native JSObjectPtr(JSObject);
[ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);

[scriptable, uuid(f649959d-dae3-4027-83fd-5b7f8c8a8815)]
[scriptable, uuid(ba602ca6-dc7a-457e-a57a-ee5b343fd863)]
interface nsIScriptSecurityManager : nsISupports
{
/**
Expand Down Expand Up @@ -240,6 +247,22 @@ interface nsIScriptSecurityManager : nsISupports
nsIDomainPolicy activateDomainPolicy();
readonly attribute boolean domainPolicyActive;

/**
* Only the parent process can directly access domain policies, child
* processes only have a read-only mirror to the one in the parent.
* For child processes the mirror is updated via messages
* and ContentChild will hold the DomainPolicy by calling
* ActivateDomainPolicyInternal directly. New consumer to this
* function should not be addded.
*/
[noscript] nsIDomainPolicy activateDomainPolicyInternal();

/**
* This function is for internal use only. Every time a child process is spawned, we
* must clone any active domain policies in the parent to the new child.
*/
[noscript, notxpcom] void cloneDomainPolicy(in DomainPolicyClonePtr aClone);

/**
* Query mechanism for the above policy.
*
Expand Down
30 changes: 28 additions & 2 deletions caps/nsScriptSecurityManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1310,9 +1310,14 @@ static StaticRefPtr<nsScriptSecurityManager> gScriptSecMan;
nsScriptSecurityManager::~nsScriptSecurityManager(void)
{
Preferences::RemoveObservers(this, kObservedPrefs);
if (mDomainPolicy)
if (mDomainPolicy) {
mDomainPolicy->Deactivate();
MOZ_ASSERT(!mDomainPolicy);
}
// ContentChild might hold a reference to the domain policy,
// and it might release it only after the security manager is
// gone. But we can still assert this for the main process.
MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_Default,
!mDomainPolicy);
}

void
Expand Down Expand Up @@ -1527,6 +1532,16 @@ nsScriptSecurityManager::GetDomainPolicyActive(bool *aRv)

NS_IMETHODIMP
nsScriptSecurityManager::ActivateDomainPolicy(nsIDomainPolicy** aRv)
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
return NS_ERROR_SERVICE_NOT_AVAILABLE;
}

return ActivateDomainPolicyInternal(aRv);
}

NS_IMETHODIMP
nsScriptSecurityManager::ActivateDomainPolicyInternal(nsIDomainPolicy** aRv)
{
// We only allow one domain policy at a time. The holder of the previous
// policy must explicitly deactivate it first.
Expand All @@ -1548,6 +1563,17 @@ nsScriptSecurityManager::DeactivateDomainPolicy()
mDomainPolicy = nullptr;
}

void
nsScriptSecurityManager::CloneDomainPolicy(DomainPolicyClone* aClone)
{
MOZ_ASSERT(aClone);
if (mDomainPolicy) {
mDomainPolicy->CloneDomainPolicy(aClone);
} else {
aClone->active() = false;
}
}

NS_IMETHODIMP
nsScriptSecurityManager::PolicyAllowsScript(nsIURI* aURI, bool *aRv)
{
Expand Down
Loading

0 comments on commit 9ae27c5

Please sign in to comment.