forked from mirrors/gecko-dev
		
	 f143125cc2
			
		
	
	
		f143125cc2
		
	
	
	
	
		
			
			MozReview-Commit-ID: DqJdTGopR9G --HG-- extra : rebase_source : e8c9eb03468c075b79013b6e0bd8b367229c24cd
		
			
				
	
	
		
			260 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | |
| /* vim: set ts=4 et sw=4 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * 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)
 | |
| 
 | |
| static nsresult
 | |
| BroadcastDomainSetChange(DomainSetType aSetType, DomainSetChangeType aChangeType,
 | |
|                          nsIURI* aDomain = nullptr)
 | |
| {
 | |
|     MOZ_ASSERT(XRE_IsParentProcess(),
 | |
|                "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_IsParentProcess()) {
 | |
|         BroadcastDomainSetChange(NO_TYPE, ACTIVATE_POLICY);
 | |
|     }
 | |
| }
 | |
| 
 | |
| DomainPolicy::~DomainPolicy()
 | |
| {
 | |
|     // The SSM holds a strong ref to the DomainPolicy until Deactivate() is
 | |
|     // invoked, so we should never hit the destructor until that happens.
 | |
|     MOZ_ASSERT(!mBlacklist && !mSuperBlacklist &&
 | |
|                !mWhitelist && !mSuperWhitelist);
 | |
| }
 | |
| 
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainPolicy::GetBlacklist(nsIDomainSet** aSet)
 | |
| {
 | |
|     nsCOMPtr<nsIDomainSet> set = mBlacklist.get();
 | |
|     set.forget(aSet);
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainPolicy::GetSuperBlacklist(nsIDomainSet** aSet)
 | |
| {
 | |
|     nsCOMPtr<nsIDomainSet> set = mSuperBlacklist.get();
 | |
|     set.forget(aSet);
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainPolicy::GetWhitelist(nsIDomainSet** aSet)
 | |
| {
 | |
|     nsCOMPtr<nsIDomainSet> set = mWhitelist.get();
 | |
|     set.forget(aSet);
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainPolicy::GetSuperWhitelist(nsIDomainSet** aSet)
 | |
| {
 | |
|     nsCOMPtr<nsIDomainSet> set = mSuperWhitelist.get();
 | |
|     set.forget(aSet);
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainPolicy::Deactivate()
 | |
| {
 | |
|     // Clear the hashtables first to free up memory, since script might
 | |
|     // hold the doomed sets alive indefinitely.
 | |
|     mBlacklist->Clear();
 | |
|     mSuperBlacklist->Clear();
 | |
|     mWhitelist->Clear();
 | |
|     mSuperWhitelist->Clear();
 | |
| 
 | |
|     // Null them out.
 | |
|     mBlacklist = nullptr;
 | |
|     mSuperBlacklist = nullptr;
 | |
|     mWhitelist = nullptr;
 | |
|     mSuperWhitelist = nullptr;
 | |
| 
 | |
|     // Inform the SSM.
 | |
|     nsScriptSecurityManager* ssm = nsScriptSecurityManager::GetScriptSecurityManager();
 | |
|     if (ssm) {
 | |
|         ssm->DeactivateDomainPolicy();
 | |
|     }
 | |
|     if (XRE_IsParentProcess()) {
 | |
|         BroadcastDomainSetChange(NO_TYPE, DEACTIVATE_POLICY);
 | |
|     }
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| void
 | |
| DomainPolicy::CloneDomainPolicy(DomainPolicyClone* aClone)
 | |
| {
 | |
|     aClone->active() = true;
 | |
|     mBlacklist->CloneSet(&aClone->blacklist());
 | |
|     mSuperBlacklist->CloneSet(&aClone->superBlacklist());
 | |
|     mWhitelist->CloneSet(&aClone->whitelist());
 | |
|     mSuperWhitelist->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(const DomainPolicyClone* aClone)
 | |
| {
 | |
|     CopyURIs(aClone->blacklist(), mBlacklist);
 | |
|     CopyURIs(aClone->whitelist(), mWhitelist);
 | |
|     CopyURIs(aClone->superBlacklist(), mSuperBlacklist);
 | |
|     CopyURIs(aClone->superWhitelist(), mSuperWhitelist);
 | |
| }
 | |
| 
 | |
| static already_AddRefed<nsIURI>
 | |
| GetCanonicalClone(nsIURI* aURI)
 | |
| {
 | |
|     nsCOMPtr<nsIURI> clone;
 | |
|     nsresult rv = aURI->Clone(getter_AddRefs(clone));
 | |
|     NS_ENSURE_SUCCESS(rv, nullptr);
 | |
|     rv = clone->SetUserPass(EmptyCString());
 | |
|     NS_ENSURE_SUCCESS(rv, nullptr);
 | |
|     rv = clone->SetPathQueryRef(EmptyCString());
 | |
|     NS_ENSURE_SUCCESS(rv, nullptr);
 | |
|     return clone.forget();
 | |
| }
 | |
| 
 | |
| NS_IMPL_ISUPPORTS(DomainSet, nsIDomainSet)
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainSet::Add(nsIURI* aDomain)
 | |
| {
 | |
|     nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
 | |
|     NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
 | |
|     mHashTable.PutEntry(clone);
 | |
|     if (XRE_IsParentProcess())
 | |
|         return BroadcastDomainSetChange(mType, ADD_DOMAIN, aDomain);
 | |
| 
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainSet::Remove(nsIURI* aDomain)
 | |
| {
 | |
|     nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
 | |
|     NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
 | |
|     mHashTable.RemoveEntry(clone);
 | |
|     if (XRE_IsParentProcess())
 | |
|         return BroadcastDomainSetChange(mType, REMOVE_DOMAIN, aDomain);
 | |
| 
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainSet::Clear()
 | |
| {
 | |
|     mHashTable.Clear();
 | |
|     if (XRE_IsParentProcess())
 | |
|         return BroadcastDomainSetChange(mType, CLEAR_DOMAINS);
 | |
| 
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainSet::Contains(nsIURI* aDomain, bool* aContains)
 | |
| {
 | |
|     *aContains = false;
 | |
|     nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
 | |
|     NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
 | |
|     *aContains = mHashTable.Contains(clone);
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainSet::ContainsSuperDomain(nsIURI* aDomain, bool* aContains)
 | |
| {
 | |
|     *aContains = false;
 | |
|     nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
 | |
|     NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
 | |
|     nsAutoCString domain;
 | |
|     nsresult rv = clone->GetHost(domain);
 | |
|     NS_ENSURE_SUCCESS(rv, rv);
 | |
|     while (true) {
 | |
|         // Check the current domain.
 | |
|         if (mHashTable.Contains(clone)) {
 | |
|             *aContains = true;
 | |
|             return NS_OK;
 | |
|         }
 | |
| 
 | |
|         // Chop off everything before the first dot, or break if there are no
 | |
|         // dots left.
 | |
|         int32_t index = domain.Find(".");
 | |
|         if (index == kNotFound)
 | |
|             break;
 | |
|         domain.Assign(Substring(domain, index + 1));
 | |
|         rv = clone->SetHost(domain);
 | |
|         NS_ENSURE_SUCCESS(rv, rv);
 | |
|     }
 | |
| 
 | |
|     // No match.
 | |
|     return NS_OK;
 | |
| 
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| DomainSet::GetType(uint32_t* aType)
 | |
| {
 | |
|     *aType = mType;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| void
 | |
| DomainSet::CloneSet(InfallibleTArray<URIParams>* aDomains)
 | |
| {
 | |
|     for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) {
 | |
|         nsIURI* key = iter.Get()->GetKey();
 | |
| 
 | |
|         URIParams uri;
 | |
|         SerializeURI(key, uri);
 | |
| 
 | |
|         aDomains->AppendElement(uri);
 | |
|     }
 | |
| }
 | |
| 
 | |
| } /* namespace mozilla */
 |